假設(shè)我們熟悉代理遞值的話,對(duì)代理我們可能又愛(ài)有恨陌选!我們先建立模型A頁(yè)面 push B頁(yè)面理郑,如果把A頁(yè)面的值傳遞到B頁(yè)面,屬性和單例傳值可以搞定咨油!但是如果Pop過(guò)程中把B頁(yè)面的值傳遞到A頁(yè)面您炉,那就可以用單例或者代理了!說(shuō)到代理役电,我們要先聲明協(xié)議赚爵,創(chuàng)建代理,很是麻煩。常常我們傳遞一個(gè)數(shù)值需要在兩個(gè)頁(yè)面間寫很多代碼冀膝,這些代碼改變頁(yè)面的整體順序唁奢,可讀性也打了折扣。所以窝剖,此時(shí)麻掸,Block是一種優(yōu)化方案。在編程過(guò)程中赐纱,Block被Obj-C看成是對(duì)象论笔,它封裝了一段代碼,這段代碼可以在任何時(shí)候執(zhí)行千所。Block可以作為函數(shù)參數(shù)或者函數(shù)的返回值狂魔,而其本身又可以帶輸入?yún)?shù)或返回值。它和傳統(tǒng)的函數(shù)指針很類似
1.定義一個(gè)Block block有兩個(gè)形參淫痰,返回值是int型的最楷,,等號(hào)右邊是block的具體實(shí)現(xiàn)待错,籽孙,block可以有參數(shù),又返回值火俄,也可以沒(méi)有
Block的訪問(wèn)權(quán)限犯建,一般情況下可以訪問(wèn),但是沒(méi)發(fā)修改變量的值瓜客,此處沒(méi)法修改的原因就是适瓦,在編譯器編譯期間把a(bǔ)的值復(fù)制到Block上產(chǎn)生了新值b,a和b是沒(méi)關(guān)系的谱仪。這個(gè)地方就是函數(shù)中的值傳遞
但是如果加上__block或者static就可以修改block內(nèi)部的值
這是因?yàn)楫?dāng)static用來(lái)修飾局部變量時(shí)玻熙,就改變了局部變量的存儲(chǔ)位置,從原來(lái)的棧中存放到靜態(tài)存儲(chǔ)區(qū)疯攒,嗦随,static 的一個(gè)作用就是保持變量?jī)?nèi)容的持久性
2.Block的內(nèi)存管理
block本身像對(duì)象一樣可以retain和release,但是block在創(chuàng)建的時(shí)候是在棧(stack)上的敬尺,并不是在堆(heap)上枚尼,他的作用域?qū)儆趧?chuàng)建時(shí)候的作用域,一旦在作用域外調(diào)用就會(huì)crash掉砂吞,但是可以使用[block copy]將棧上的block復(fù)制到堆上署恍,就可以在創(chuàng)建時(shí)候的作用域外調(diào)用
3.Block的循環(huán)引用
在MRC下,我們使用__block防止循環(huán)引用;在ARC下呜舒,我們使用__weak防止循環(huán)引用锭汛。原理就是:ARC中,Block中如果引用了__strong修飾符的自動(dòng)變量袭蝗,則相當(dāng)于Block對(duì)該變量的引用計(jì)數(shù)+1唤殴。
這一點(diǎn)其實(shí)是在第一點(diǎn)的一個(gè)小的衍生。當(dāng)在block內(nèi)部使用成員變量的時(shí)候到腥,比如:
@interface ViewController : UIViewController
{
NSString *_string;
}
@end
在block創(chuàng)建中:
_block = ^(){
NSLog(@string %@, _string);
};
這里的_string相當(dāng)于是self->_string朵逝;那么block是會(huì)對(duì)內(nèi)部的對(duì)象進(jìn)行一次retain。也就是說(shuō)乡范,self會(huì)被retain一次配名。當(dāng)self釋放的時(shí)候,需要block釋放后才會(huì)對(duì)self進(jìn)行釋放晋辆,但是block的釋放又需要等self的dealloc中才會(huì)釋放渠脉。如此一來(lái)變形成了循環(huán)引用,導(dǎo)致內(nèi)存泄露瓶佳。
修改方案是新建一個(gè)__block scope的局部變量芋膘,并把self賦值給它,而在block內(nèi)部則使用這個(gè)局部變量來(lái)進(jìn)行取值霸饲。因?yàn)開(kāi)_block標(biāo)記的變量是不會(huì)被自動(dòng)retain的为朋。
__block ViewController *controller = self;
_block = ^(){
NSLog(@string %@, controller->_string);
};