循環(huán)引用
某個(gè)對(duì)象有一個(gè)copy或者strong成員變量或者屬性,這時(shí)block內(nèi)部直接引用了成員變量或者self掂林,這樣就產(chǎn)生了self持有block成員伟葫,block成員持有self,就會(huì)導(dǎo)致循環(huán)引用蝗茁。因?yàn)閟elf本身就是一個(gè)strong類型的變量。蘋果官方的建議是:傳進(jìn)block之前寻咒,把self轉(zhuǎn)換成weak automatic的變量哮翘,這樣在block中就不會(huì)出現(xiàn)對(duì)self的強(qiáng)引用。如果在block執(zhí)行完成之前毛秘,self被釋放饭寺,weakSelf也會(huì)置為nil阻课。weak類型相對(duì)比較安全,因?yàn)榭梢栽卺尫藕笞詣?dòng)置為nil艰匙,不會(huì)引起野指針限煞。
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ì)引起循環(huán)引用:
NSLog(@"init-->value:%@,address=%p,self=%p",self.person,self.person,self);
myBlock1 = ^(void){
//這樣不會(huì)造成循環(huán)引用
NSLog(@"execute1-->value:%@,address=%p,weakSelf=%p",weakSelf.person,weakSelf.person,weakSelf);
};```
3. 直接使用self,會(huì)循環(huán)引用:Xcode會(huì)給警告
```myBlock2 = ^(void){
//這樣造成循環(huán)引用
NSLog(@"execute2--> value:%@,address=%p,self=%p",self.person,self.person,self);
};```
4. 要執(zhí)行的方法抽取出來糖埋,也不會(huì)循環(huán)引用:
myBlock3 = ^(void){
//這樣也不會(huì)造成循環(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ì)循環(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();```