block塊存儲(chǔ)位置
block塊根據(jù)情況有兩種可能的存儲(chǔ)位置衡招,一種存在代碼區(qū),一種存在堆區(qū)每强。
1蚁吝、如果block塊沒有訪問處于棧區(qū)的變量(比如局部變量)旱爆,也沒有訪問堆區(qū)的變量(比如我們alloc創(chuàng)建的對(duì)象),那就存在代碼區(qū)窘茁,即使訪問了全局變量怀伦,也依然存在代碼區(qū)。
2山林、如果訪問了棧區(qū)或者堆區(qū)的變量房待,那就會(huì)被存在堆區(qū)(實(shí)際存在棧區(qū),ARC下會(huì)自動(dòng)拷貝到堆區(qū))驼抹。
關(guān)于存在堆區(qū)的情況桑孩,有一點(diǎn)需要注意的是,堆區(qū)是不斷變化的框冀,不斷地有變量的創(chuàng)建和銷毀流椒,如果block塊沒有強(qiáng)引用,那也隨時(shí)可能被銷毀明也,這就導(dǎo)致一旦在銷毀時(shí)訪問block塊宣虾,程序就會(huì)崩潰,所以温数,在定義block時(shí)绣硝,內(nèi)存修飾最好用strong或者copy。而且在使用時(shí)也最好先判斷一下block是否為空撑刺,比如:
if(!block){
return;
}block();
1
2
3
4
既然在修飾block時(shí)鹉胖,使用了strong,那么另一個(gè)問題就需要注意了够傍,也就是循環(huán)引用甫菠。
當(dāng)使用了strong修飾后,self會(huì)強(qiáng)引用block冕屯,而如果在block中又需要訪問self的一些屬性或者方法淑蔚,從而調(diào)用了self,這時(shí)self和block就進(jìn)入循環(huán)引用愕撰,容易內(nèi)存溢出。
解決的辦法時(shí)在block中的需要用到self時(shí)醋寝,事先將self用__weak修飾搞挣,這樣互相引用的一方就不再是強(qiáng)引用了。
比如:
__weak ViewController *weakSelf =self;self.block = ^{? ? weakSelf.str= @"123";};
1
2
3
4
但是這樣還不夠音羞,在多線程下囱桨,單單使用weakSelf,可能前一刻weakSelf還在嗅绰,后面需要用時(shí)卻被釋放掉了舍肠,畢竟弱引用是不穩(wěn)定的搀继,這時(shí)候就需要又使用一個(gè)修飾符__strong來在block中修飾,是不是操碎了心翠语。
因此更好的釋放方式如下:
__weak__typeof(self) *weakSelf =self;self.block= ^{? ? __strong__typeof(self) strongSelf = weakSelf;if(strongSelf) {? ? ? ? strongSelf.str= @"123";? ? }// 如果不用了叽躯,應(yīng)置為空strongSelf.block=nil;};
1
2
3
4
5
6
7
8
9
平常使用block的情況很多,很多人往往都是直接拿樣例代碼改著用了肌括,不知道為什么要這么修飾block点骑,也不知道weakSelf、strongSelf有什么用谍夭。這里就從存儲(chǔ)位置來解釋為什么要這樣修飾block黑滴,從而又會(huì)造成循環(huán)引用的問題,最后如何去解決他紧索。希望可以幫助大家更好的理解手中的每一行代碼袁辈。
block塊根據(jù)情況有兩種可能的存儲(chǔ)位置,一種存在代碼區(qū)珠漂,一種存在堆區(qū)晚缩。
1、如果block塊沒有訪問處于棧區(qū)的變量(比如局部變量)甘磨,也沒有訪問堆區(qū)的變量(比如我們alloc創(chuàng)建的對(duì)象)橡羞,那就存在代碼區(qū),即使訪問了全局變量济舆,也依然存在代碼區(qū)卿泽。
2、如果訪問了棧區(qū)或者堆區(qū)的變量滋觉,那就會(huì)被存在堆區(qū)(實(shí)際存在棧區(qū)签夭,ARC下會(huì)自動(dòng)拷貝到堆區(qū))。
關(guān)于存在堆區(qū)的情況椎侠,有一點(diǎn)需要注意的是第租,堆區(qū)是不斷變化的,不斷地有變量的創(chuàng)建和銷毀我纪,如果block塊沒有強(qiáng)引用慎宾,那也隨時(shí)可能被銷毀,這就導(dǎo)致一旦在銷毀時(shí)訪問block塊浅悉,程序就會(huì)崩潰趟据,所以,在定義block時(shí)术健,內(nèi)存修飾最好用strong或者copy汹碱。而且在使用時(shí)也最好先判斷一下block是否為空,比如:
if(!block){
return;
}block();
1
2
3
4
既然在修飾block時(shí)荞估,使用了strong咳促,那么另一個(gè)問題就需要注意了稚新,也就是循環(huán)引用。
當(dāng)使用了strong修飾后跪腹,self會(huì)強(qiáng)引用block褂删,而如果在block中又需要訪問self的一些屬性或者方法,從而調(diào)用了self尺迂,這時(shí)self和block就進(jìn)入循環(huán)引用笤妙,容易內(nèi)存溢出。
解決的辦法時(shí)在block中的需要用到self時(shí)噪裕,事先將self用__weak修飾蹲盘,這樣互相引用的一方就不再是強(qiáng)引用了。
比如:
__weak ViewController *weakSelf =self;self.block = ^{? ? weakSelf.str= @"123";};
1
2
3
4
但是這樣還不夠膳音,在多線程下召衔,單單使用weakSelf,可能前一刻weakSelf還在祭陷,后面需要用時(shí)卻被釋放掉了苍凛,畢竟弱引用是不穩(wěn)定的,這時(shí)候就需要又使用一個(gè)修飾符__strong來在block中修飾兵志,是不是操碎了心醇蝴。
因此更好的釋放方式如下:
__weak__typeof(self) *weakSelf =self;self.block= ^{? ? __strong__typeof(self) strongSelf = weakSelf;if(strongSelf) {? ? ? ? strongSelf.str= @"123";? ? }// 如果不用了,應(yīng)置為空strongSelf.block=nil;};
1
2
3
4
5
6
7
8
9
平常使用block的情況很多想罕,很多人往往都是直接拿樣例代碼改著用了悠栓,不知道為什么要這么修飾block,也不知道weakSelf按价、strongSelf有什么用惭适。這里就從存儲(chǔ)位置來解釋為什么要這樣修飾block,從而又會(huì)造成循環(huán)引用的問題楼镐,最后如何去解決他癞志。希望可以幫助大家更好的理解手中的每一行代碼。