假設我們熟悉代理遞值的話,對代理我們可能又愛有恨!我們先建立模型A頁面 push B頁面,如果把A頁面的值傳遞到B頁面,屬性和單例傳值可以搞定!但是如果Pop過程中把B頁面的值傳遞到A頁面,那就可以用單例或者代理了!說到代理,我們要先聲明協議,創建代理,很是麻煩。常常我們傳遞一個數值需要在兩個頁面間寫很多代碼,這些代碼改變頁面的整體順序,可讀性也打了折扣。所以,此時,Block是一種優化方案。在編程過程中,Block被Obj-C看成是對象,它封裝了一段代碼,這段代碼可以在任何時候執行。Block可以作為函數參數或者函數的返回值,而其本身又可以帶輸入參數或返回值。它和傳統的函數指針很類似
1.定義一個Block block有兩個形參,返回值是int型的,,等號右邊是block的具體實現,,block可以有參數,又返回值,也可以沒有
Block的訪問權限,一般情況下可以訪問,但是沒發修改變量的值,此處沒法修改的原因就是,在編譯器編譯期間把a的值復制到Block上產生了新值b,a和b是沒關系的。這個地方就是函數中的值傳遞
但是如果加上__block或者static就可以修改block內部的值
這是因為當static用來修飾局部變量時,就改變了局部變量的存儲位置,從原來的棧中存放到靜態存儲區,,static 的一個作用就是保持變量內容的持久性
2.Block的內存管理
block本身像對象一樣可以retain和release,但是block在創建的時候是在棧(stack)上的,並不是在堆(heap)上,他的作用域屬於創建時候的作用域,一旦在作用域外調用就會crash掉,但是可以使用[block copy]將棧上的block復制到堆上,就可以在創建時候的作用域外調用
3.Block的循環引用
在MRC下,我們使用__block防止循環引用;在ARC下,我們使用__weak防止循環引用。原理就是:ARC中,Block中如果引用了__strong修飾符的自動變量,則相當於Block對該變量的引用計數+1。
這一點其實是在第一點的一個小的衍生。當在block內部使用成員變量的時候,比如
在block創建中:
這裡的_string相當於是self->_string;那麼block是會對內部的對象進行一次retain。也就是說,self會被retain一次。當self釋放的時候,需要block釋放後才會對self進行釋放,但是block的釋放又需要等self的dealloc中才會釋放。如此一來變形成了循環引用,導致內存洩露。
修改方案是新建一個__block scope的局部變量,並把self賦值給它,而在block內部則使用這個局部變量來進行取值。因為__block標記的變量是不會被自動retain的。