第37條 理解“塊”這一概念

塊的強大之處是:在聲明它的范圍里,所有變量都可以為其所捕獲。這就是說,那個范圍里的全部變量,在塊里依然可用。比如:
int additional = 5;
int (^addBlock)(int a, int b) = ^(int a, int b){
return a + b + additional;
};
默認的情況下,為塊所捕獲的變量,是不可以在塊里修改的。不過,聲明變量的時候可以加上__block修飾符。這樣就可以在塊內(nèi)修改了。

如果塊所捕獲的變量是對象類型,那么就會自動保留它。系統(tǒng)在釋放這個塊的時候,也會將其一并釋放。這就引出了一個與塊有關的重要問題。塊本身可視為對象。實際上,在其他Objective-C 對象所能響應的選擇子中,有很多塊也是可以響應的。而最重要之處則在于,塊本身也和其他對象一樣,有引用計數(shù)。當最后一個指向塊的引用移走之后,塊就回收了。
回收時也會釋放塊所捕獲的變量。以便平衡捕獲時所執(zhí)行的保留操作。

如果將塊定義在Objective-C類的實例方法中,那么除了可以訪問類的所有實例變量之外,還可以使用self變量。塊總能修改實例變量,所以在聲明時,無須加__block.不過,如果通過讀取或寫入操作捕獲了實例變量,那么也會自動把self變量一并捕獲了,因為實例變量是與self所指代的實例變量關聯(lián)在一起的。

全局塊/棧塊/堆塊

定義塊的時候,其所占的內(nèi)存區(qū)域是分配在棧中的。這就是說,塊只在定義它的哪個范圍內(nèi)有效。
void (^block)();
if ( ...)
{
block = ^{
NSLog(@"Block A");
};
}
else
{
block = ^{
NSLog(@"Block B");
};
}

block();

定義在if以及else 語句中的兩個塊都分配在棧內(nèi)存中。這兩個塊只能保證在對應的if 或else 語句范圍內(nèi)有效。

為解決此問題,可以給塊對象發(fā)送copy消息以拷貝之。這樣的話,就可以把塊從棧復制到堆了。拷貝后的塊,就可以在定義它的哪個范圍之外使用。而且,一旦復制到堆上,塊就可以成了帶引用計數(shù)的對象了。后續(xù)的復制操作都不會真的執(zhí)行復制,只是遞增塊對象的引用計數(shù)。
如果不再使用這個塊,那就應將其釋放。當引用計數(shù)降為0后,分配在堆上的塊會像其他對象一樣,為系統(tǒng)所回收。而分配在棧上的塊則無須明確釋放,因為棧內(nèi)存本來就會自動回收。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容