Block中的循环引用,循环引用

不会产生循环援用的block

在讲block的轮回援引难点此前,我们需求先领悟一下iOS的内部存款和储蓄器管理机制和block的基本知识

正文首要介绍ARC下block的大循环援用难点,比方表明引起循环援用的情景和对应的缓和方案。

简来说之那总体实际正是为了防范循环引用,下边结合网络上各位大咖的剖析精髓解析解析

大部分GCD方法

1 dispatch_async(dispatch_get_main_queue(), ^{
2     [self doSomething];
3 });

因为self并不曾对GCD的block进行富有,未有变异巡回引用。前段时间自己尚未碰到使用GCD引致循环援用的场所,假设某种场景self对GCD的block实行了具备,则才有希望招致循环援用。

 

iOS的内部存储器管理机制

在讲block的轮回援引难点在此之前,大家须要先掌握一下iOS的内部存款和储蓄器管理机制和block的基本知识

block对于其变量都会产生强援用(retain),对于self也会变成强援引(retain) ,而只要self自身对block也是强引用的话,就能够造成 强援用循环,不能自由——形成内部存储器走漏
什么是循环援引:对象A持有对象B,对象B持有对象A,互相持有,最后促成三个对象都不能够放出。

block并不是属性值,而是有时变量

 1 - (void)doSomething {
 2     [self testWithBlock:^{
 3         [self test];
 4     }];
 5 }
 6 
 7 - (void)testWithBlock:(void(^)())block {
 8     block();
 9 }
10 
11 - (void)test {
12     NSLog(@"test");
13 }

那边因为block只是二个一时半刻变量,self并未对其兼具,所以并未有形成循环援用

 

Objective-C在iOS中不扶助GC(垃圾回笼卡塔尔机制,而是采取的引用计数的艺术管理内部存款和储蓄器。

iOS的内部存款和储蓄器管理机制

Objective-C在iOS中不扶持GC机制,而是使用的援引计数的措施管理内部存款和储蓄器。

在引用计数中,每叁个指标担当掩护对象具有援引的计数值。当叁个新的引用指向对象时,引用计数器就比比皆已经,当去掉多个援用时,援引计数就依次减少。当援用计数到零时,该目的就将释放占领的能源。

作者们透过开关房间的灯为例来�表明援引计数机制。

图片 1援用《Pro Multithreading and Memory Management for iOS and OS X》中的图片

图中,“供给照明的总人口”即对应我们要说的援用计数值。

  1. 先是私人商品房进来办公,“须求照明的人头”加1,计数值从0变为1,因而必要开灯;
  2. 随后每当有人进来办公室,“须求照明的总人口”就加1。如计数值从1形成2;
  3. 每当有人下班离开办公室,“需求照明的人口”加减1如计数值从2形成1;
  4. 提及底一位下班离开办公室时,“须要照明的人数”减1。计数值从1形成0,因而需求关灯。

在Objective-C中,”对象“相当于办公的照明设备,”对象的行使景况“相当于步入办公室的人。上班踏入办公的人对办公照明设备发出的动作,与Objective-C中的对应关系如下表

对照明设备所做的动作 对Objective-C对象所做的动作
开灯 生成对象
需要照明 持有对象
不需要照明 释放对象
关灯 废弃对象

利用计数作用计算须要照明的食指,使办公室的照明获得了很好的管住。同样,使用援用计数效用,对象也就会博取很好的军事拘禁,那正是Objective-C内部存储器管理,如下图所示

图片 2引用《Pro Multithreading and Memory Management for iOS and OS X》中的图片

Objective-C对象方法 说明
alloc/new/copy/mutableCopy 创建对象,引用计数加1
retain 引用计数加1
release 引用计数减1
dealloc 当引用计数为0时调用
[NSArray array] 引用计数不增加,由自动释放池管理
[NSDictionary dictionary] 引用计数不增加,由自动释放池管理

至于机关释放,不是本文的重中之重,这里就不讲了。

Objective-C对象所有权修饰符 说明
__strong 对象默认修饰符,对象强引用,在对象超出作用域时失效。其实就相当于retain操作,超出作用域时执行release操作
__weak 弱引用,不持有对象,对象释放时会将对象置nil。
__unsafe_unretained 弱引用,不持有对象,对象释放时不会将对象置nil。
__autoreleasing 自动释放,由自动释放池管理对象

巡回引用项景:
1、block在主函数体用到了self / self.变量 / [self 方法],意味着:block对self 进行具备操作;
2、self证明了质量变量block,block用copy来修饰,意味着:self对block进行富有操作,会产生循环引用;
诸如下图,未来这么写Xcode直接就能有警示出来告诉您那边貌似retain cycle了呀!!

block使用对象被提前释放

有这种境况,假设不只是ClassA持有了myBlock,ClassB也兼具了myBlock。

图片 3

当ClassA被someObj对象释放后

图片 4

那个时候,ClassA对象已经被放出,而myBlock还是被ClassB持有,未有自由;要是myBlock那么些时被调节,而此时ClassA已经被释放,当时拜谒的ClassA将是一个nil对象(使用__weak修饰,对象释放时会置为nil),而吸引错误。

 

另一个附近错误接受是,开拓者担忧循环援引错误(如上所述不会冒出循环引用的动静),使用__weak。比如

1 __weak typeof(self) weakSelf = self;
2 dispatch_async(dispatch_get_main_queue(), ^{
3     [weakSelf doSomething];
4 });

因为将block作为参数字传送给dispatch_async时,系统会将block拷贝到堆上,况且block会持有block中用到的对象,因为dispatch_async并不知道block中指标会在什么样时候被放走,为了有限支撑系统调解施行block中的职分时其目的未有被意外释放掉,dispatch_async必需谐和retain一次对象(即self),职分成功后再release对象(即self)。但那边运用__weak,使dispatch_async未有扩展self的援用计数,那使得在系统在调整推行block以前,self只怕已被销毁,但系统并不知道那一个情形,招致block实践时访谈已经被放出的self,而达不到预期的结果。

 

引用计数(Reference Count卡塔尔国

block的基本知识

block的基本知识这里就不细说了,能够看看本人的小说说说Objective-C中的block

图片 5

注:假如是在MRC情势下,使用__block修饰self,则这时block访谈被放走的self,则会形成crash。 

本场景下的代码

 1 // ClassA.m
 2 - (void)test {
 3     __weak MyClass* weakSelf = self;
 4     double delayInSeconds = 10.0f;
 5     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
 6     dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
 7         NSLog(@"%@", weakSelf);
 8     });
 9 }
10 
11 // ClassB.m
12 - (void)doSomething {
13     NSLog(@"do something");
14     ClassA *objA = [[ClassA alloc] init];
15     [objA test];
16 }

运作结果

[5988:435396] do something
[5988:435396] self:(null)

化解方法:

对于这种场所,就不该利用__weak来修饰对象,让dispatch_after对self进行具备,保险block试行时self还没被放出。

 

在援引计数中,每一个指标承当维护对象具有引用的计数值。当一个新的引用指向对象时,引用流量计就雨后春笋,当去掉二个援用时,引用计数就依次减少。当引用计数到零时,该指标就将释放占领的财富。

循环援用难点

多个目的互相持有,那样就能促成循环援引,如下图所示

图片 6四个对象相互持有

图中,对象A持有对象B,对象B持有对象A,相互持有,最终引致八个对象都不能自由。

鉴于block会对block中的对象开展具备操作,就也正是具备了内部的指标,而只要这时候block中的对象又两全了该block,则会导致循环援用。如下,

typedef void;@property (copy, nonatomic) block myBlock;@property (copy, nonatomic) NSString *blockString;- testBlock { self.myBlock = ^() { //其实注释中的代码,同样会造成循环引用 NSString *localString = self.blockString; //NSString *localString = _blockString; //[self doSomething]; };}

注:以下调用注释掉的代码同样会招致循环引用,因为无论是是经过self.blockString还是_blockString,或是函数调用[self doSomething],因为豆蔻年华旦 block中用到了指标的属性或许函数,block就能够持有该对象并非该指标中的有些属性恐怕函数。

当有someObj持有self对象,那时的涉及图如下。

图片 7

当someObj对象release self对象时,self和myblock互相引用,retainCount都为1,产生循环引用

图片 8

解决措施:

__weak typeof weakSelf = self;self.myBlock = ^() { NSString *localString = weakSelf.blockString;};

使用__weak修饰self,使其在block中不被全数,打破循环引用。最早情状如下

图片 9

当someObj对象释放self对象时,Self的retainCount为0,走dealloc,释放myBlock对象,使其retainCount也为0。

图片 10

实在以上循环援用之处超轻易开掘,因为当时Xcode就能够报告急察方告。而发生在三个目的间的时候,Xcode就检查实验不出去了,那往往就便于被忽略。

//ClassB@interface ClassB : NSObject@property (strong, nonatomic) ClassA *objA;- doSomething;@end //ClassA@property (strong, nonatomic) ClassB *objB;@property (copy, nonatomic) block myBlock;- testBlockRetainCycle { ClassB* objB = [[ClassB alloc] init]; self.myBlock = ^() { [objB doSomething]; }; objB.objA = self;}

图片 11

解决方法:

- testBlockRetainCycle { ClassB* objB = [[ClassB alloc] init]; __weak typeof weakObjB = objB; self.myBlock = ^() { [weakObjB doSomething]; }; objB.objA = self;}

将objA对象weak,使其不在block中被全体

注:以上使用__weak打破循环的不二秘技只在ARC下才有效,在MRC下应该运用__block

仍然,在block施行完后,将block置nil,那样也能够打破循环援用

- testBlockRetainCycle { ClassB* objB = [[ClassB alloc] init]; self.myBlock = ^() { [objB doSomething]; }; objA.objA = self; self.myBlock(); self.myBlock = nil;}

那般做的缺点是,block只会施行三次,因为block被置nil了,要再一次行使的话,供给再度赋值。

在开垦工程中,开掘一些同桌并不曾完全理解循环援用,认为只要有block之处就能要用__weak来修饰对象,那样完全没须求,以下两种block是不会引致循环引用的。

dispatch_async(dispatch_get_main_queue(), ^{ [self doSomething];});

因为self并未对GCD的block实行具有,未有变异巡回引用。近日小编还未碰到使用GCD招致循环援引的情景,要是某种场景self对GCD的block进行了独具,则才有一点都不小可能率以致循环援用。

- doSomething { [self testWithBlock:^{ [self test]; }];}- testWithBlock:)block { block();}- test { NSLog;}

此地因为block只是二个一时变量,self并从未对其抱有,所以未有导致循环援用

看下边例子,有这种气象,倘若不只是ClassA持有了myBlock,ClassB也会有所了myBlock。

图片 12

当ClassA被someObj对象释放后

图片 13

此时,ClassA对象已经被假释,而myBlock依然被ClassB持有,未有自由;假设myBlock这么些时被调节,而此时ClassA已经被放走,那时候做客的ClassA将是三个nil对象(使用__weak修饰,对象释放时会置为nil),而吸引错误。

另贰个左近错误接收是,开拓者思念循环援引错误(如上所述不会产出循环援引的气象),使用__weak。比如

__weak typeof weakSelf = self;dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf doSomething];});

因为将block作为参数字传送给dispatch_async时,系统会将block拷贝到堆上,况且block会持有block中用到的对象,因为dispatch_async并不知道block中目的会在怎么时候被假释,为了确认保障系统调整推行block中的职责时其目的未有被意外释放掉,dispatch_async必须和睦retain叁遍对象,任务成功后再release对象。但那边运用__weak,使dispatch_async未有扩大self的引用计数,那使得在系统在调节实施block早先,self也许已被销毁,但系统并不知道那么些情景,引致block施行时访谈已经被放飞的self,而达不到预期的结果。

注:假若是在MRC形式下,使用__block修饰self,则当时block访谈被放飞的self,则会导致crash。

该现象下的代码

// ClassA.m- test { __weak MyClass* weakSelf = self; double delayInSeconds = 10.0f; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^{ NSLog(@"%@", weakSelf); });}// ClassB.m- doSomething { NSLog(@"do something"); ClassA *objA = [[ClassA alloc] init]; [objA test];}

运行结果

[5988:435396] do something[5988:435396] self:

减轻形式:

对于这种场合,就不该接纳__weak来修饰对象,让dispatch_after对self实行富有,保险block实施时self尚未被放走。

再有意气风发种情形,在block实施起来时self对象尚未被放飞,而举办进度中,self被释放了,当时拜见self时,就能够发出错误。

对此这种处境,应该在block中对 对象使用__strong修饰,使得在block时期对 对象具有,block试行达成后,解除其具有。

- testBlockRetainCycle { ClassA* objA = [[ClassA alloc] init]; __weak typeof weakObjA = objA; self.myBlock = ^() { __strong typeof strongWeakObjA = weakObjA; [strongWeakObjA doSomething]; }; objA.objA = self;}

注:此办法只好保障在block施行时期对象不被放走,若是目的在block实施实行此前已经被释放了,该办法也无效。

巡回援用例子

block推行进度中目的被放出

还会有大器晚成种现象,在block执行起来时self对象还没被放走,而实行进度中,self被放飞了,当时访谈self时,就能够生出错误。

对于这种气象,应该在block中对 对象使用__strong修饰,使得在block时期对 对象具备,block实施达成后,清除其兼具。

1 - (void)testBlockRetainCycle {
2     ClassA* objA = [[ClassA alloc] init];
3     __weak typeof(objA) weakObjA = objA;
4     self.myBlock = ^() {
5         __strong typeof(weakObjA) strongWeakObjA = weakObjA;
6         [strongWeakObjA doSomething];
7     };
8     objA.objA = self;
9 }

 

注:此办法只可以作保在block试行时期对象不被放出,借使目的在block实践实施以前曾经被放飞了,该办法也行不通。

 

仿照效法资料:block的循环引用难题

大家经过按键房间的灯为例来�表达援用计数机制。

只要自身想在block里面更改一些变量的值大概应用部分变量,如下图那样写Xcode直接报错 並且付出了消除办法提醒出来了 那点还挺机智的,那么大家应用__block修饰之后,再次在block里面使用,就不会出标题了,完美。

图片 14

图片 15

援引《Pro Multithreading and Memory Management for iOS and OS X》中的图片

解决

图中,“须求照明的人口”即对应大家要说的引用计数值。

率先私家步向办公,“须求照明的人数”加1,计数值从0变为1,由此要求开灯;

图片 16

之后每当有人步入办公,“需求照明的食指”就加1。如计数值从1变成2;

采纳部分变量.png

每当有人下班离开办公,“要求照明的食指”加减1如计数值从2产生1;

在使用block的地方:
__block typeof(self) bself = self;          // 适用MRC模式,
__block NSString *tempStr = @"abc";
__block int a = 0; //当修饰变量时,表示这个变量值能在block中被修改
__weak typeof(self) weakself = self;     // 适用ARC模式

最后一人下班离开办公时,“须求照明的人头”减1。计数值从1产生0,由此必要关灯。

关于——Block在MRC和ARC方式的区分
1)__block在MRC下有四个效果与利益
同意在Block中做客和修改部分变量
禁止Block对所引述的靶子开展隐式retain操作

在Objective-C中,”对象“约等于办公的照明设备,”对象的应用条件“也正是步向办公的人。上班踏入办公室的人对办公照明设备发出的动作,与Objective-C中的对应关系如下表

2)__block在ARC下只有一个成效
允许在Block中访谈和改换部分变量

对待明设备所做的动作对Objective-C对象所做的动作

怎么时候在 block 中没有必要采取 weakSelf???

开灯生成对象

  • 大部GCD方法,因为self并不曾对GCD的block进行具备,未有变异巡回援用。近些日子自己还未境遇使用GCD引致循环引用的气象,若是某种场景self对GCD的block举办了富有,则才有希望招致循环援引。

急需照明持有对象

dispatch_async(dispatch_get_main_queue(), ^{
[self doSomething];
});

不必要照明释放对象

  • 大多数动漫效果,当动漫截止时,UIView 会结束全体那个 block,block 对象就能自由掉,进而 block 会释放掉对于 self 的具备。整个内部存款和储蓄器引用关系被撤废。

关灯放弃对象

[UIView animateWithDuration:0.2 animations:^{
self.alpha = 1;
}];

利用计数功效计算必要照明的总人口,使办公室的照明得到了很好的管住。同样,使用援用计数作用,对象也就会收获很好的治本,那正是Objective-C内部存款和储蓄器管理,如下图所示

  • block并不是指标的习性 / 变量,而是方法的参数 / 一时变量,这里因为block只是一个一时半刻变量,self并从未对其持有,所以并未有产生循环引用

图片 17

.- (void) testWithBlock:(void(^)())block {
block();
}

援引《Pro Multithreading and Memory Management for iOS and OS X》中的图片

  • 还会有朝气蓬勃种状态,block归于Person对象,在另四个类里面使用的时候从不构成互周旋有,这时也没有必要weakSelf。

  • 接受GCD的时候,这么写实际是谬误的,实际不是观望block将在为了避防循环援引而选拔weakSelf,像上边这种写法,就是八花九裂的:

MRC(Manual Reference Counting卡塔尔(英语:State of Qatar)中挑起应用计数变化的章程

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf doSomething];
});

Objective-C对象方法求证

因为将block作为参数字传送给dispatch_async时,系统会将block拷贝到堆上,并且block会持有block中用到的靶子,因为dispatch_async并不知道block中目的会在怎么着时候被放出,为了保证系统调整施行block中的职务时其目的未有被意外释放掉,dispatch_async必需协调retain三回对象(即self),任务成功后再release对象(即self)。但此间运用__weak,使dispatch_async未有扩大self的引用计数,那使得在系统在调度推行block以前,self大概已被销毁,但系统并不知道这几个情况,引致block试行时访问已经被放出的self,而达不到预期的结果。

alloc/new/copy/mutableCopy制造对象,引用计数加1

总结
1 在 Block 内假设供给拜谒 self 的艺术、变量,建议使用 weakSelf。
2 借使在 Block 内须要再三 访谈 self,则须要动用 strongSelf。

retain引用计数加1

release引用计数减1

dealloc当征引计数为0时调用

[NSArray array]援用计数不扩充,由机关释放池管理

[NSDictionary dictionary]引用计数不扩充,由活动释放池管理

机关释放池

关于机关释放,不是本文的首要性,这里就不讲了。

ARC(Automatic Reference Counting卡塔尔(英语:State of Qatar)中内存管理

Objective-C对象全体权修饰符表达

__strong对象默许修饰符,对象强引用,在对象超过功效域时失效。其实就也正是retain操作,超出作用域时实施release操作

__weak弱援引,不持有对象,对象释放时会将指标置nil。

__unsafe_unretained弱引用,不持有对象,对象释放时不会将目的置nil。

__autoreleasing自动释放,由活动释放池管理对象

block的基本知识

block的基本知识这里就不细说了。

巡回援引难点

八个指标相互持有,那样就能够促成循环援引,如下图所示

图片 18

五个目的彼此持有

图中,对象A持有对象B,对象B持有对象A,互相持有,最终促成五个目的都不能够放出。

block中循环援用难题

鉴于block会对block中的对象进行具有操作,就一定于具有了内部的目的,而生机勃勃旦这时候block中的对象又有着了该block,则会促成循环引用。如下,

typedef void(^block)();

@property (copy, nonatomic) block myBlock;

@property (copy, nonatomic) NSString *blockString;

- (void)testBlock {

self.myBlock = ^() {

//其实注释中的代码,相仿会招致循环引用

NSString *localString = self.blockString;

//NSString *localString = _blockString;

//[self doSomething];

};

}

注:以下调用注释掉的代码相似会酿成循环引用,因为不管是通过self.blockString照旧_blockString,或是函数调用[self doSomething],因为假设block中用到了对象的习性恐怕函数,block就能有着该目的并不是该对象中的有些属性大概函数。

当有someObj持有self对象,这时的关系图如下。

图片 19

当someObj对象release self对象时,self和myblock相互援引,retainCount都为1,形成循环引用

图片 20

扫除办法:

__weak typeof(self) weakSelf = self;

self.myBlock = ^() {

NSString *localString = weakSelf.blockString;

};

使用__weak修饰self,使其在block中不被全体,打破循环援引。伊始情况如下

图片 21

当someObj对象释放self对象时,Self的retainCount为0,走dealloc,释放myBlock对象,使其retainCount也为0。

图片 22

实质上以上循环援用的事态超级轻易发觉,因为那个时候Xcode就能报告急察方告。而发出在五个对象间的时候,Xcode就检验不出去了,那频仍就轻松被忽略。

//ClassB

@interface ClassB : NSObject

@property (strong, nonatomic) ClassA *objA;

- (void)doSomething;

@end

//ClassA

@property (strong, nonatomic) ClassB *objB;

@property (copy, nonatomic) block myBlock;

- (void)testBlockRetainCycle {

ClassB* objB = [[ClassB alloc] init];

self.myBlock = ^() {

[objB doSomething];

};

objB.objA = self;

}

图片 23

缓慢解决形式:

- (void)testBlockRetainCycle {

ClassB* objB = [[ClassB alloc] init];

__weak typeof(objB) weakObjB = objB;

self.myBlock = ^() {

[weakObjB doSomething];

};

objB.objA = self;

}

将objA对象weak,使其不在block中被抱有

注:以上使用__weak打破循环的章程只在ARC下才使得,在MRC下相应使用__block

抑或,在block实践完后,将block置nil,那样也足以打破循环引用

- (void)testBlockRetainCycle {

ClassB* objB = [[ClassB alloc] init];

self.myBlock = ^() {

[objB doSomething];

};

objA.objA = self;

self.myBlock();

self.myBlock = nil;

}

如此做的症结是,block只会实践二次,因为block被置nil了,要重复利用以来,要求再行赋值。

局地不会导致循环援用的block

在开拓工程中,开采存些同校并不曾完全领悟循环援引,以为只要有block的地点就能够要用__weak来修饰对象,那样完全没须求,以下二种block是不会以致循环引用的。

大部分GCD方法

dispatch_async(dispatch_get_main_queue(), ^{

[self doSomething];

});

因为self并未对GCD的block实行具备,未有变异巡回引用。近来笔者还未蒙受使用GCD招致循环引用的现象,假若某种场景self对GCD的block进行了具有,则才有相当的大恐怕招致循环援用。

block实际不是属性值,而是一时半刻变量

- (void)doSomething {

[self testWithBlock:^{

[self test];

}];

}

- (void)testWithBlock:(void(^)())block {

block();

}

- (void)test {

NSLog(@"test");

}

此间因为block只是贰个临时变量,self并未对其负有,所以未有形成循环援用

block使用对象被提前释放

看上边例子,有这种场合,假如不只是ClassA持有了myBlock,ClassB也持有了myBlock。

图片 24

当ClassA被someObj对象释放后

图片 25

此刻,ClassA对象已经被放走,而myBlock仍旧被ClassB持有,没有自由;若是myBlock那个时被调节,而这个时候ClassA已经被假释,此时拜谒的ClassA将是一个nil对象(使用__weak修饰,对象释放时会置为nil),而引发错误。

另三个布满错误使用是,开辟者忧虑循环引用错误(如上所述不会产出循环引用的情状),使用__weak。比如

__weak typeof(self) weakSelf = self;

dispatch_async(dispatch_get_main_queue(), ^{

[weakSelf doSomething];

});

因为将block作为参数字传送给dispatch_async时,系统会将block拷贝到堆上,並且block会持有block中用到的对象,因为dispatch_async并不知道block中指标会在怎么时候被放走,为了保证系统调整实践block中的职分时其指标未有被意外释放掉,dispatch_async必需协和retain壹遍对象(即self),职务到位后再release对象(即self)。但那边运用__weak,使dispatch_async未有扩张self的援引计数,那使得在系统在调整实行block以前,self大概已被销毁,但系统并不知道这么些处境,诱致block施行时访谈已经被放出的self,而达不到预期的结果。

注:假若是在MRC格局下,使用__block修饰self,则那时候block访谈被放出的self,则会促成crash。

这场合下的代码

// ClassA.m

- (void)test {

__weak MyClass* weakSelf = self;

double delayInSeconds = 10.0f;

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));

dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

NSLog(@"%@", weakSelf);

});

}

// ClassB.m

- (void)doSomething {

NSLog(@"do something");

ClassA *objA = [[ClassA alloc] init];

[objA test];

}

运营结果

[5988:435396] do something

[5988:435396] self:(null)

减轻方式:

对于这种现象,就不应有接纳__weak来修饰对象,让dispatch_after对self举办富有,保险block实践时self还没被保释。

block试行进程中指标被假释

还会有大器晚成种现象,在block施行起来时self对象还未被保释,而进行进度中,self被放出了,那时做客self时,就能够发出错误。

对此这种气象,应该在block中对 对象使用__strong修饰,使得在block时期对 对象具备,block施行完成后,息灭其独具。

- (void)testBlockRetainCycle {

ClassA* objA = [[ClassA alloc] init];

__weak typeof(objA) weakObjA = objA;

self.myBlock = ^() {

__strong typeof(weakObjA) strongWeakObjA = weakObjA;

[strongWeakObjA doSomething];

};

objA.objA = self;

}

注:此办法只好保障在block试行时期对象不被假释,要是指标在block实施实施早前早就被放出了,该办法也行不通。

本文由星彩网app下载发布于计算机编程,转载请注明出处:Block中的循环引用,循环引用

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。