什么是循环引用?
这是我们不希望看到的,因为此时 A 和 B 两个类的实例都不能被 deinit
因为我们在 var a前面加上了 weak,就是向编译器表明我们不希望持有 a
闭包需要使用 weak self 的情况
发生这种情况的主要原因是self持有了closure,而closure有持有了self,所以就造成了循环引用,从而小明对象没有被释放。
一句话解释:只有当block直接或间接的被self持有时,才需要weak self。
// 这种情况没必要 [self fetchDataWithSucess:^{ [self doSomething]; }]; //这种情况就有必要 self.onTapEvent = ^{ [self doSomething]; };
block中为什么会用到weakself是因为要避免循环引用,一旦出现循环引用那么对象就会常驻内存。如果一个应用程序里面你有很多循环引用,那么内存占用就会比较大,这当然是谁都不想看到的结果。那么问题的重点就是:什么时候会出现循环引用?再先来看一个例子:
NSArray *anArray = @[@"1", @"2", @"3"]; [anArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [self doSomething:idx]; }];
这种情况下,block中retain了self,当block中的代码被执行完后,self就会被ARC释放。所以不需要处理weakself的情况。
再来看一个例子
@interface aViewController () @property (nonatomic, strong) void(^aBlock)(id obj, NSUInteger idx, BOOL *stop); @end __weak aViewController *weakSelf = self; self.aBlock = ^(id obj, NSUInteger idx, BOOL *stop) { [weakSelf doSomething:idx]; }
这个例子的区别在于:block被self strong引用。所以结果就是block中引用了self,self引用了block。那么这个时候,如果你不使用weakself,则self和block永远都不会被释放。
那么是不是遇到block都要使用weakself呢?当然不是,而且如果全部使用weakself,会出现你想执行block中的代码时,self已经被释放掉了的情况。
另外,在处理weakself时,有两种做法:__weak和__unsafe_unretained。两种做法各有推荐,有的人觉得后者从字面上更好理解,而有的人觉得前者更加安全,因为self被释放时会自动指向nil。有的人又说了,就是应该让app崩溃才能发现问题所在。这个,看个人吧。