Block循环引用以及解决方案
此贴推荐重点阅读↓
参考贴:深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用
此贴推荐重点阅读↑造成循环引用的原因(套用别人的成果)
======
//情况一 : 不会循环引用, 不会内存泄露
- (void)case1 {
NSLog(@"case 1 Click");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.name = @"case 1";
});
}
======
//情况二 : 不会循环引用,不会内存泄露
- (void)case2 {
NSLog(@"case 2 Click");
__weak typeof(self) weakSelf = self;
[self.teacher requestData:^(NSData *data) {
typeof(weakSelf) strongSelf = weakSelf;
strongSelf.name = @"case 2";
}];
}
======
//情况三 : 典型的循环引用
- (void)case3 {
NSLog(@"case 3 Click");
[self.teacher requestData:^(NSData *data) {
self.name = @"case 3";
}];
}
======
//情况四 : 不会循环引用,self不再强引用teacher,但若block不执行,依然会循环引用
- (void)case4 {
NSLog(@"case 4 Click");
[self.teacher requestData:^(NSData *data) {
self.name = @"case 4";
self.teacher = nil;
}];
}
======
//情况五 : 不会循环引用,self未强引用 Teacher的实例对象
- (void)case5 {
NSLog(@"case 5 Click");
Teacher *t = [[Teacher alloc] init];
[t requestData:^(NSData *data) {
self.name = @"case 5";
}];
}
======
//情况六 不会循环引用,self.teacher不再强引用case6Block,但若block不执行,依然会循环引用
- (void)case6 {
NSLog(@"case 6 Click");
[self.teacher callCase6BlackEvent];
self.teacher.case6Block = ^(NSData *data) {
self.name = @"case 6";
self.teacher.case6Block = nil;
};
}
解决方法 1
NSLog(@"case 2 Click");
__weak typeof(self) weakSelf = self;
[self.teacher requestData:^(NSData *data) {
typeof(weakSelf) strongSelf = weakSelf;
strongSelf.name = @"case 2";
}];
解决方法 2
使用 @weakify , @strongify 这两个宏定义
@weakify(self); // 定义了一个__weak的self_weak_变量
[RACObserve(self, name) subscribeNext:^(NSString *name) {
@strongify(self); // 局域定义了一个__strong的self指针指向self_weak
self.outputLabel.text = name;
}];
补充内容(1)
这样也会造成循环引用
ABCBlock *abc = [[ABCBlock alloc] init];
abc.block = ^{
self.ssss = @"";
};
self.aaaa = [NSMutableArray arrayWithCapacity:0];
[self.aaaa addObject:abc];
}
- (void)dealloc{
NSLog(@"-------- dealloc ---------");
}
以上这个和 情况五 相似.
虽然 ABCBlock的实例并不是当前类的成员属性,但其实该类(self)的其他成员属性却依旧持有abc (将其添加进数组中), 所以以上这种情况,也是不会执行dealloc()方法的.需要注意.
补充内容(2)
@weakify | @strongify
@weakify(<#object#>);
@strongify(<#object#>)
#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