block簡介
block跟swift中的閉包(closure)比較:
基本一樣突梦,都常用于值的回調(diào),特別是在多線程的網(wǎng)絡(luò)請求回調(diào)中,使用起來極為方便咧擂。
- Block格式:
block的開頭是“^”,接著是由小括號(hào)所包起來的參數(shù)列檀蹋,行為主體由大括號(hào)包起來松申。block有四種類型,分別是無參無返回、無參有返回贸桶、有參有返回舅逸、以及有參無返回,而一般使用的block都是有參block皇筛,因?yàn)槭褂胋lock主要就是進(jìn)行參數(shù)的傳遞琉历。 - Block的循環(huán)引用問題:
使用block時(shí)要特別注意類的循環(huán)引用:例如在一個(gè)控制器中,self強(qiáng)指針指向一個(gè)對(duì)象水醋,而這個(gè)對(duì)象又強(qiáng)指針指向一個(gè)block旗笔,而在block中,又強(qiáng)指針指向了self拄踪,從而造成循環(huán)引用蝇恶,導(dǎo)致內(nèi)存無法釋放,造成內(nèi)存泄露惶桐。
如何解決block的循環(huán)引用:
解決循環(huán)引用的方法撮弧,常用__weak來打斷強(qiáng)引用,例如用__weak來定義一個(gè)weakself來指向self的地址耀盗,如果self被釋放想虎,weakself指向的地址變?yōu)閚il,從而打斷引用環(huán)叛拷。需要注意的是舌厨,__weak是ARC專有的,__unsafe__unretained可以用在ARC忿薇,也可以用于MRC裙椭,但__unsafe__unretained是“assign”形式,如果指向的對(duì)象被釋放署浩,其指針地址保持不變揉燃,如果繼續(xù)使用該指針,就會(huì)出現(xiàn)“野指針”筋栋。 - 關(guān)于block內(nèi)存管理:
當(dāng)block內(nèi)部沒有引用外部變量時(shí)炊汤,block存放在全局區(qū);在運(yùn)行時(shí)發(fā)現(xiàn), block的本質(zhì)是靜態(tài)的static修飾的,所有全局可用, 這也是block可以跨類跨控制器調(diào)用的原因, 在MRC下弊攘,當(dāng)block內(nèi)部引用外部變量時(shí)抢腐,block存放在棧區(qū);當(dāng)對(duì)該棧區(qū)的block進(jìn)行copy操作時(shí)襟交,block將存放在堆區(qū)迈倍。在ARC下,當(dāng)block內(nèi)部引用外部變量時(shí)捣域,block存放在堆區(qū)啼染;關(guān)于堆區(qū)與棧區(qū)的區(qū)別宴合,棧區(qū)主要存放局部變量,定義的參數(shù)等迹鹅,在函數(shù)結(jié)束卦洽,系統(tǒng)會(huì)自動(dòng)回收其內(nèi)存空間,而堆區(qū)一般用程序員自行分配釋放徒欣,若程序員不釋放逐样,程序結(jié)束時(shí),由系統(tǒng)回收打肝。總的來說挪捕,使用棧區(qū)更為快捷粗梭,而使用堆區(qū)更為靈活。 - Block的使用注意點(diǎn):
如果要在block中修改外部變量级零,當(dāng)變量是static全局變量時(shí)断医,block可以直接修改,如果不是奏纪,可以用__block關(guān)鍵字來修飾鉴嗤,就可以在block內(nèi)修改變量的值。
block代碼示例
- 無參數(shù)無返回值的block
void(^helloBlock)() = ^ { NSLog(@"hello") } - 無參數(shù)有返回值的blokc
int(^intBlock)() = ^ { return 5 } - 有參數(shù) 無返回值的block
void(^giveInt)(int) = ^(int a){ NSLog(@"%d",a) } - 有參數(shù)有返回值block
int(^giveInt)(int) = ^(int a){ NSLog(@"%d",a) return a+1 }