我知道一個Objective-C塊可以捕獲並設置其封閉範圍之外的變量值。它是如何做到的?塊如何捕獲其封閉範圍之外的變量?
回答
在塊對象的代碼體中,可以用五種不同的方式處理變量。
您可以參考三個標準類型的變量,就像你從一個函數將:
- 全局變量,包括靜態當地人
- 全局函數(這在技術上不變量)
- 地方來自封閉示波器的變量和參數
塊還支持兩種其他類型的變量:
在功能級別是
__block
變量。這些在塊(和封閉範圍)內是可變的,並且如果任何引用塊被複制到堆中,它們將被保留。
const
進口。最後,方法的實現中,塊可以參考物鏡-C實例變量 - 請參見對象和塊的變量。
以下規則適用於一個塊中使用的變量:
全局變量是可訪問的,包括存在的封閉詞法範圍內的靜態變量。
傳遞給塊的參數是可訪問的(就像函數的參數一樣)。
將封閉詞法作用域本地的棧(非靜態)變量作爲
const
變量捕獲。它們的值取自程序中塊表達式的位置。在嵌套塊中,該值是從最近的封閉範圍捕獲的。
由
__block
存儲修飾符聲明的封閉詞法範圍的局部變量由引用提供,因此可以修改。任何更改都反映在封閉詞法作用域中,包括在同一個封閉詞法作用域內定義的任何其他塊。這些在__block存儲類型中有更詳細的討論。
在塊的詞法範圍內聲明的局部變量,其行爲與函數中的局部變量完全相同。
塊的每次調用都會提供該變量的新副本。這些變量可以用作
const
或塊中封閉塊中的引用變量。
它實際上相當簡單,在鏘的模塊實現規格說明,在"Imported Variables"部分。
當編譯器遇到一個像座:
^{ if(numBalloons > numClowns) abort(); }
它會創建一個文本結構,包括 - 除其他事項外 - 在這裏是很重要的兩個元素。有一個指向塊中可執行代碼的函數指針,並且在塊內引用每個變量的const
字段。事情是這樣的:
struct __block_literal_1 {
/* other fields */
void (*invoke)(struct __block_literal_1 *);
/* ... */
const int numBalloons;
const int numClowns;
};
注意,invoke
功能將一個指向真實被定義在這裏的那種結構;也就是說,Block在執行代碼時自動進入。因此,代碼可以訪問結構的成員。
權的聲明之後,編譯器創建的模塊,簡單的使用引用變量初始化在struct
正確的字段的定義:
struct __block_literal_1 __block_literal_1 = {
/* Other fields */
__block_invoke_2, /* This function was also created by the compiler. */
/* ... */
numBalloons, /* These two are the exact same variables as */
numClowns /* those referred to in the Block literal that you wrote. *
};
然後,invoke
函數內部,引用到捕獲的變量與結構的其他任何成員一樣,the_block->numBalloons
。
對象類型變量的情況稍微複雜一點,但同樣的原則適用。
基本上,對於每個捕獲的本地變量,塊「對象」在塊對象中包含一個變量(如塊對象的「實例變量」)。 (Josh Caswell的答案提供了有關如何實現的更多細節。)創建塊時,此時每個捕獲的局部變量的值將被複制到塊內的相應變量中。只要變量在塊內部使用,它就會在塊內使用該變量。
- 1. 封閉本地範圍變量與全局範圍變量 - Python
- 2. 在封閉範圍內修改變量
- 3. 封閉範圍
- 4. 在封閉範圍
- 5. 我如何獲得編譯指令來偵聽其範圍之外的變量?
- 6. 塊內外的變量範圍
- 7. JavaScript關閉 - 評估()和捕獲變量在Eval()的範圍
- 8. 在jquery範圍之外的alert變量
- 9. 在範圍變量中捕獲單元
- 10. javascript中的封閉範圍
- 11. 在最接近的外部範圍中捕獲變量
- 12. 在其範圍外使用變量
- 13. 從其範圍外訪問變量?
- 14. 嘗試捕獲塊變量超出範圍
- 15. 訪問其範圍之外的變量值
- 16. 爲什麼scala try塊允許重新定義封閉範圍的變量?
- 17. 與lambda函數Python中封閉的範圍變量
- 18. 從嵌套函數的封閉範圍訪問變量
- 19. 在封閉範圍內更新變量的SSA表示
- 20. NameError:在封閉範圍內賦值之前引用的自由變量'ar'
- 21. Python:NameError:在封閉範圍內賦值之前引用的自由變量're'
- 22. Python:在封閉範圍內賦值之前引用的自由變量'numpy'
- 23. Python的封:寫入變量父範圍
- 24. 關閉範圍內的捕獲函數
- 25. 如何在當前範圍/塊之外定義一個常量?
- 26. 變量在其範圍之外不可見
- 27. 如何更新XMLHttprequest之外的範圍變量
- 28. 我該如何更新$範圍之外的控制器變量。
- 29. 如何在Go模板中分析範圍之外的變量?
- 30. 如何在javascript中訪問當前範圍之外的變量?
我認爲它基本上對待它,就好像外部變量不超出範圍時,他們被定義的範圍結束,使用塊很多,但我不會算作自己的專家 – Fonix