2013-07-24 25 views
6

據我所知,塊的標量變量需要__block存儲類型才能看到它們的更新,但是何時需要對象?我相信__weak應該在捕獲塊中使用的自引用時使用,但我沒有看到何時需要對普通對象實際使用__block存儲類型。何時在對象引用上使用__block關鍵字與ARC

+0

而且[什麼__weak和__block之間的區別參考?](http://stackoverflow.com/questions/11773342/what-the-difference-between-weak-and-block-reference) –

+0

我特別問:當'__block'存儲類型sh在使用ARC時應該用於非標量非自對象引用?如果其他鏈接回答這個問題,我已經錯過了。 – chinabuffet

+0

@chinabuffet:標量類型和對象指針類型的工作方式沒有區別。 – newacct

回答

15

__block對於標量變量是必需的,如果您想要用塊內的代碼更改它們的值。捕獲的標量在塊內顯示爲const,因此無法更改。如果你有一個指向一個對象的指針,相同的區別適用 - 捕獲的指針本身將是一個const指針,因此不能被修改,但指向的對象可以通過塊內的代碼修改。如果要更改指向的對象,則指針本身必須更改,因此指針必須用__block類型聲明。沒有必要將對象本身聲明爲__block,而只是指向對象的指針,並且只有在必須更改指針時纔是如此。

如果你有正確的心智模式,塊沒有那麼混亂。重要的是要知道,塊最初是分配在堆棧上的,當彈出堆棧幀時,詞法範圍被破壞時會消失。如果希望塊在創建塊的詞法作用域的整個生命週期內都處於掛起狀態,請使用Block_copy()將其移動到堆中,或將其發送到-copy消息。當一個塊被複制到堆中時,所有捕獲的const變量都會繼續,並且這些const變量指向的所有對象都將被保留。從堆中刪除塊時,將釋放const變量指向的所有對象。

__block變量「引擎蓋下」具有編譯器使用(並且您看不到)的額外間接層,包含在塊中,因此當塊被複制到堆中時,變量也會被捕獲到__block變量,並且將不可見指針調整爲指向這些__block變量的新堆位置。這意味着__block變量的地址可能會更改,因此如果使用該地址,請小心。您也可以看到__block變量在某種意義上位於塊的「外部」,因此可以從塊外部的代碼讀取和修改這些變量。

我已經簡單地說,但你可以在這裏找到更好的解釋,在日益複雜所列:

http://ios-blog.co.uk/tutorials/programming-with-blocks-an-overview/

http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

http://www.mikeash.com/pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html

+0

因此,如果該塊作爲參考傳遞給某個地方,那麼是否將接收該塊作爲參數需要立即複製該塊以便將來使用它? – chinabuffet

+0

如果塊引用可能超出定義塊的詞法範圍(堆棧幀),則必須將其複製以將塊對象移動到堆中。我認爲在創建塊時進行復制比將這些副本發生在遠離創建的位置更安全。 – Fred

0

它們用於功能級變量。這些在塊(和封閉範圍)內是可變的,並且如果任何引用塊被複制到堆中,它們將被保留。用__block存儲修飾符聲明的封閉詞彙範圍的本地變量由引用提供,因此可以修改。任何更改都會反映在封閉詞法作用域中,包括在同一個封閉詞法作用域中定義的任何其他塊。

__block變量生活在一個變量的詞法作用域和所有塊,並宣佈或變量的詞法範圍內創建的塊拷貝之間共享存儲。因此,如果在幀中聲明的塊的任何副本存活超過幀的末尾(例如,通過在某處等待以後執行),那麼存儲器將在存儲器堆棧幀的銷燬中倖存下來。因此,在需要修改塊內的對象時或者在堆棧框架銷燬後需要該對象時,請使用它們。

相關問題