目前只有Mac 10.6 和iOS 4有支援。Block是由一堆可執行的程式組成,也可以稱做沒有名字的Function (Anonymous function)
AD:
详解Objective-c block 应用是本文要介绍的内容,主要介绍的是Objective-c block 应用,不多说,先来看详细内容。
Apple 在C , Objective-C , C++ 加上Block 這個延申用法。目前只有Mac 10.6 和iOS 4有支援。Block 是 由一堆可執行的程式組成,也可以稱做沒有名字的Function (Anonymous function)。如果是Mac 10.6 或 iOS 4.0 之前的平台可以利用 http://code.google.com/p/plblocks/ 這個project得以支援Block語法。
Apple有一個叫做GCD(Grand Central Dispach)的新功能,用在同步處理(concurrency)的環境下有更好的效率。Block語法產生的動機就是來自於GCD,用Block包好 一個工作量交給GCD,GCD有一個宏觀的視野可以來分配CPU,GPU,Memory的來下最好的決定。
Block 簡介
Block其實行為和Function很像,最大的差別是在可以存取同一個Scope的變數值。
Block 實體會長成這樣
^(傳入參數列) {行為主體};
Block實體開頭是"^",接著是由小括號所包起來的參數列(比如 int a, int b, float
c),行為的主體由大括號包起來,專有名詞叫做block
literal。行為主體可以用return回傳值,型別會被compiler自動辦識出來。如果沒有參數列要這樣寫(void)。
看個列子
這是代表Block會回傳輸入值的平方值(int a 就是參數列,return a*a; 就是行為主體)。記得主體裡最後要加";"因為是敘述,而整個{}最後也要要加";"因為Block是個物件實體。
用法就是
很怪吧。後面小括號裡的5 會被當成a的輸入值然後經由Block輸出5*5 = 25指定給result這個變數。
有沒有簡單一點的方法不然每次都要寫這麼長?有。接下來要介紹一個叫Block Pointer的東西來簡化我們的寫法。
Block Pointer是這樣宣告的
回傳值 (^名字) (參數列);
直接來看一個列子
使用Block Pointer的例子
int result = square(5); // 感覺上不就是funtion的用法嗎?也可以把Block Pointer當成參數傳給一個function,比如說
傳入一個有一個int輸入和int輸出的Block 型別的參數
呼叫這個myFunction的時候就是這樣呼叫
或是不用block pointer 直接給一個block 實體,就這樣寫
當成Objective-C method 的傳入值的話都是要把型別寫在變數前面然後加上小括號,因些應該就要這樣寫
讀文至此是不是對Block有基本的認識? 接下來我們要談談Block相關的行為和特色
首先是來看一下在Block裡面存取外部變數的方法
存取變數
1. 可以讀取和Block pointer同一個scope的變數值:
我們再來看一個很有趣的例子
事實上呢,myPtr在其主體用到outA這個變數值的時候是做了一個copy的動作把outA的值copy下來。所以之後outA即使換了新的值對於myPtr裡copy的值是沒有影響到的。
要注意的是,這個指的值是變數的值,如果這個變數的值是一個記憶體的位置,換句話說,這個變數是個pointer的話,它指到的值是可以在block裡被改變的。
原本mutableArray的值是{@"one",@"two",@"three"}在block裡被更改mutableArray所指向的物件後,mutableArray的值就會被成{@"one",@"two"}
2. 直接存取static 的變數
甚至可以在block裡面直接改變outA的值比如這樣寫
3. Block Variable
在某個變數前面如果加上修飾字__block 的話(注意block前有兩個下底線),這個變數又稱為block variable。那麼在block裡就可以任意修改此變數值,變數值的改變也可以知道。
因為myPtr和myPtr2都有用到num這個block variable,最後result的值就會是7
生命周期和記憶體管理
因為block也是繼承自NSObject,所以其生命周期和記憶體的管理也就非常之重要。
block一開始都是被放到stack裡,換句話說其生命周期隨著method或function結束就會被回收,和一般變數的生命周期一樣。
關於記憶體的管理請遵循這幾個要點
1. block pointer的實體會在method或function結束後就會被清掉
2. 如果要保存block pointer的實體要用-copy指令,這樣block pointer就會被放到heap裡
(1)block 主體裡用到的block variable 也會被搬到heap 而有新的記憶體位置,且一並更新有用到這個block variable 的block都指到新的位置
(2)一般的variable值會被copy
(3)如果主體裡用到的variable是object的話,此object會被retain, block release時也會被release
(4)block variable 裡用到的object是不會被retain的
首先來看一下這個例子
此程式由genBlock裡產生的block再指定給main function的outBlock變數,執行這個程式會得到
(註:有時候把 genBlock裡的a 去掉就可以跑出結果的情形,這是系統cache住記憶體,並不是inBlock真得一直存在,久了還是會被回收,千萬不要以為是對的寫法)
表示我們用到了不該用的記憶體,在這個例子的情況下是在genBlock裡的inBlock變數在return的時候就被回收了,outBlock無法有一個合法的記憶體位置-retainCount就沒意義了。
如果這個時候需要保留inBlock的值就要用-copy指令,將genBlock改成
這樣[inBlock copy]的回傳值就會被放到heap,就可以一直使用(記得要release)
執行結果是
再次提醒要記得release outBlock。
如果一回傳[inBlock copy]的值就不再需要的時候可以這樣寫
-copy指令是為了要把block 從stack搬到heap,autorelease是為了平衝retainCount加到autorelease oop ,回傳之後等到事件結束就清掉。
接下來是block存取到的local variable是個物件的型別,然後做copy 指令時
結果會印出
這個結果和上面2.3提到的一樣,local variable被retain了
那再來試試2.4,在local variable前面加上__block
執行的結果就是會
Block Copying注意事項
如果在Class method裡面做copying block動作的話
1. 在Block裡如果有直接存取到self,則self會被retain
2. 在Block裡如果取存到instance variable (無論直接或是從accessor),則self會被retain
3. 取存到local variable所擁有的object時,這個object會被retain
讓我們來看一個自訂的Class
在main 裡使用如下
其執行的結果為
因為在MyObject的建構子裡myLog這個block pointer用了title這個instance variable然後就會retain self也就是MyObject的物件。
盡量不要這樣寫,會造成retain cycle,改善的方法是把建構子改成這樣
在Block主體裡用newTitle這個變數而不是title。這樣self就不會被retain了。
最後談一個小陷井
這樣很可能就會當掉了,因為myLog 實體在if 或是else結束後就被清掉了。要記得。
要用copy來解決這個問題,但要記得release
小结:详解Objective-c block 应用的内容介绍完了,希望本文对你有所帮助!更多相关内容请参考编辑推荐。
FROM:http://mobile.51cto.com/iphone-279757.htm
Posted on 九月 29, 2011 by pingsun in Android
最近更新了Nexus s 2.3.6,可是再次进入Recovery的时候,却出现了,黄色感叹号。于是折腾啊,哎。。。查了好多资料才知道,原来官方原版Recovery的进入方法略有不通。原厂Recovery的进入方法,按电源键确认进入Recovery后,你会看见一个Android机器人和一个感叹号,这时候快速再次按下VolumeUP和Power键,就能成功进入原厂的Recovery模式了..
中文排序:有可能会想到pinying4j.jar 这个貌似 太极端了
可以通过CursorWrapper来实现。
还是先留一坑吧