下面是理論部分:
1、block的定義
1 // 聲明和實現寫在一起,就像變量的聲明實現 int a = 10; 2 int (^aBlock)(int, int) = ^(int num1, int num2) { 3 4 return num1 * num2; 5 6 }; 7 // 聲明和實現分開,就像變量先聲明後實現 int a;a = 10; 8 int (^cBlock)(int,int); 9 cBlock = ^(int num1,int num2) 10 { 11 return num1 * num2; 12 };
其中,定義了一個名字為aBlock的blocks對象,並攜帶了相關信息:
1、aBlock 有兩個形式參數,分別為int類型;
2、aBlock 的返回值為int 類型;
3、等式右邊就是blocks的具體實現;
4、^ 帶邊blocks聲明和實現的標示(關鍵字);
當然,你可以定義其他形式的block。e.g:無返回值,無形式參數等;
1 void (^bBlock)() = ^() 2 { 3 int a = 10; 4 printf(num = %d,a); 5 };
2、blocks 訪問權限
blocks可以訪問局部變量,但是不能修改。
1 int a = 10; 2 int (^dBlock)(int) = ^(int num) 3 { 4 a++;//not work! 5 return num * a; 6 };
此處不能修改的原因是在編譯期間確定的,編譯器編譯的時候把a的值復制到block作為一個新變量(假設是a‘ = 10),此時a'和a是沒有關系的。
這個地方就是函數中的值傳遞。如果要修改就要加關鍵字:__block或者static
1 __block int a = 7; 2 int (^dBlock)(int) = ^(int num) 3 { 4 a++;// work! 5 return num * a; 6 };
3、block的調用
block調用就像調用函數一樣。e.g:
1int
c = aBlock(10,10);
bBlock();
4、block 應用
假設我們熟悉代理遞值的話,對代理我們可能又愛有恨!我們先建立模型A頁面 push B頁面,如果把A頁面的值傳遞到B頁面,屬性和單例傳值可以搞定!但是如果Pop過程中把B頁面的值傳遞到A頁面,那就可以用單例或者代理了!說到代理,我們要先聲明協議,創建代理,很是麻煩。常常我們傳遞一個數值需要在兩個頁面間寫很多代碼,這些代碼改變頁面的整體順序,可讀性也打了折扣。所以,此時,block是一種優化方案!
5、 block的內存管理
block本身是像對象一樣可以retain,和release。但是,block在創建的時候,它的內存是分配在棧(stack)上,而不是在堆(heap)上。他本身的作於域是屬於創建時候的作用域,一旦在創建時候的作用域外面調用block將導致程序崩潰。比如下面的例子。 我在view did load中創建了一個block: