循環(huán)引用
某個(gè)對象有一個(gè)copy或者strong成員變量或者屬性,這時(shí)block內(nèi)部直接引用了成員變量或者self,這樣就產(chǎn)生了self持有block成員,block成員持有self,就會導(dǎo)致循環(huán)引用。因?yàn)閟elf本身就是一個(gè)strong類型的變量。蘋果官方的建議是:傳進(jìn)block之前,把self轉(zhuǎn)換成weak automatic的變量,這樣在block中就不會出現(xiàn)對self的強(qiáng)引用。如果在block執(zhí)行完成之前,self被釋放,weakSelf也會置為nil。weak類型相對比較安全,因?yàn)榭梢栽卺尫藕笞詣?dòng)置為nil,不會引起野指針。
weakSelf聲明
-
__weak typeof(self) weakSelf = self;
這句話的意思是聲明了一個(gè)self類型的weak指針,名字叫做weakSelf. typeof是用來求參數(shù)類型的,這里也就是來求self的類型。這樣定義出的weakSelf就是和self是一個(gè)類型,并且是原self的一個(gè)弱引用。 __weak typeof(&*self) weakSelf = self;__weak MyViewController *weakSelf = self;
代碼演示
- 聲明幾個(gè)block和一個(gè)屬性:
@interface ViewController (){ void(^myBlock1)(void);//該block參數(shù)為void,返回值為void void(^myBlock2)(void); void(^myBlock3)(void); } @property (nonatomic,copy) NSString *person; @end - 使用weakSelf不會引起循環(huán)引用:
NSLog(@"init-->value:%@,address=%p,self=%p",self.person,self.person,self);
myBlock1 = ^(void){
//這樣不會造成循環(huán)引用
NSLog(@"execute1-->value:%@,address=%p,weakSelf=%p",weakSelf.person,weakSelf.person,weakSelf);
};```
3. 直接使用self,會循環(huán)引用:Xcode會給警告
```myBlock2 = ^(void){
//這樣造成循環(huán)引用
NSLog(@"execute2--> value:%@,address=%p,self=%p",self.person,self.person,self);
};```
4. 要執(zhí)行的方法抽取出來,也不會循環(huán)引用:
myBlock3 = ^(void){
//這樣也不會造成循環(huán)引用,已經(jīng)抽取出要執(zhí)行的方法
[weakSelf myBlock3Func];
};```
NSLog(@"execute3--> value:%@,address=%p,self=%p",self.person,self.person,self);
}
- block不是self的屬性或者變量時(shí),在block內(nèi)使用self也不會循環(huán)引用:
//block不是self的屬性時(shí),block內(nèi)部使用self也不是循環(huán)引用
Animal *animal = [[Animal alloc] init];
animal.animalBlock = ^(void){
NSLog(@"animal-value:%@,address=%p,self=%p",self.person,self.person,self);
};```
6. block的調(diào)用如下:
```myBlock1();
myBlock2();
myBlock3();
animal.animalBlock();```