ibireme 写的 YYKit 很好用,连放出的 Demo 都有很多好用的代码片度。

在 iOS 中使用的 block 中如果使用到了 self,为了避免循环引用(Retain Cycle),通常都会用 __weak 将 self 重新引用一下即可。

AFNetworking 是这样做的:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)startMonitoring {
...
__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
...
}

而 YYKit 作者 ibireme 在 YYKitMacro.h 中用宏来定义使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
Synthsize a weak or strong reference.
Example:
@weakify(self)
[self doSomething^{
@strongify(self)
if (!self) return;
...
}];
*/
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif
#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif

使用的话就很方便了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- (void)setItem:(YYPhotoGroupItem *)item {
...
@weakify(self);
[_imageView setImageWithURL:item.largeImageURL placeholder:item.thumbImage options:kNilOptions progress:^(NSInteger receivedSize, NSInteger expectedSize) {
@strongify(self);
if (!self) return;
CGFloat progress = receivedSize / (float)expectedSize;
progress = progress < 0.01 ? 0.01 : progress > 1 ? 1 : progress;
if (isnan(progress)) progress = 0;
self.progressLayer.hidden = NO;
self.progressLayer.strokeEnd = progress;
} transform:nil completion:^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
@strongify(self);
if (!self) return;
self.progressLayer.hidden = YES;
if (stage == YYWebImageStageFinished) {
self.maximumZoomScale = 3;
if (image) {
self->_itemDidLoad = YES;
[self resizeSubviewSize];
[self.imageView.layer addFadeAnimationWithDuration:0.1 curve:UIViewAnimationCurveLinear];
}
}
}];
...
}

嗯,很耐撕。