2017-08-27 41 views
-1

因此,這段代碼是一個逃避關閉,我也明白,它的@escaping是必需的,因爲函數轉義和追加或變更完成處理。爲什麼值類型不需要@escaping或顯式自我而不是轉義閉包?

var completionHandlers: [() -> Void] = [] 
func someFunctionWithEscapingClosure(completionHandler: @escaping() -> Void) { 
completionHandlers.append(completionHandler) 
} 

func someFunctionWithNonescapingClosure(closure:() -> Void) { 
closure() 
} 

class SomeClass { 
var x = 10 
func doSomething() { 
    someFunctionWithEscapingClosure { self.x = 100 } 
    someFunctionWithNonescapingClosure { x = 200 } 
} 
} 

let instance = SomeClass() 
instance.doSomething() 
print(instance.x) 
// Prints "200" 

completionHandlers.first?() 
print(instance.x) 
// Prints "100」 

然而,這個簡單的代碼並不要求值類型被標記爲轉義,即使它改變了變量x。

var x: Int = 0 

func x (y: Int) { 
x += y 
} 

x (y: 7) 

print (x) 

這混淆了我,因爲我不明白,爲什麼在第二個自代碼可以隱式評估,但有逃避關閉的自我要求(如果它被稱爲)。

+0

在你的第二個例子中,沒有閉合。所以沒有什麼可以標記爲'@ escaping'。這只是一個函數(儘管像你的變量一樣將'x'命名爲混淆)。只有關閉參數需要標記爲'@ escaping'。也許我不明白你的問題... – Rob

回答

1

我明白它是@escaping是必需的,因爲該函數轉義並附加或更改完成處理程序。

從該短語中不完全清楚您明白@escaping的含義。這意味着,此功能參數得到存儲而不是立即執行,並扔掉。

這是你的第一個例子會發生什麼:我們都交給一個() -> Void和而不是僅僅執行它,我們把它添加到一個持續的數組。

在你的第二個例子中,沒有函數參數(只是一個低的Int),所以這個問題永遠不會出現。

原因爲什麼問題出現的函數參數是函數是閉包,所以當函數被存儲時,其環境中的其他東西可以被存儲。這可以產生意想不到的後果,所以你不得不承認,你說@escaping意識到了這一點。

+0

(順便說一句,一個功能是引用類型,不是值類型,這實際上是我們逃避正在發生時承認的原因之一。) – matt

+0

但什麼關於將類實例傳遞給函數?它們是引用類型,即使將它附加到函數外部的變量上,也不需要指出@escaping。 – User9123

+0

你讀過我的回答了嗎?類實例不是函數。所以它不是封閉的。 – matt

相關問題