在 ARC 环境下,我们会使用 _weak
修饰符来修饰一个变量防止其在 block
中被循环引用,特殊情况下还会在 block
中使用 _strong
修饰符来修饰这个变量如下:
__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
这是因为在 block
中调用 self
会引起循环引用,同时在 block
中需要对 weakSelf
进行 strong
操作,保证 self
不会被释放,当block
执行完会自动释放该 strongSelf
。但实际上 strong
是为了防止野指针,而 block
里大部分是用 weakSelf
访问 self
的属性,而不是局部变量,我们也不可能主动释放 self
,这样看来就没有 strong
的必要了当然不排除有特殊情况。
除开上面这种一般写法,我们看看 YYKit 中是怎么使用 weak&strong
:
#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
/**
Example:
@weakify(self)
[self doSomething^{
@strongify(self)
if (!self) return;
...
}];
*/
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
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
还有来自 libextobjc的这种写法:
#define weakify(...) \\
autoreleasepool {} \\
metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)
#define strongify(...) \\
try {} @finally {} \\
_Pragma("clang diagnostic push") \\
_Pragma("clang diagnostic ignored \\"-Wshadow\\"") \\
metamacro_foreach(rac_strongify_,, __VA_ARGS__) \\
_Pragma("clang diagnostic pop")
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
其中细节可以参考这篇文章 http://www.jianshu.com/p/3d6c4416db5e