2017-04-04 55 views
3

非逃避關閉我有一個extension Array的形式:麻煩與斯威夫特3

extension Array 
{ 
    private func someFunction(someClosure: (() -> Int)?) 
    { 
     // Do Something 
    } 

    func someOtherFunction(someOtherClosure:() -> Int) 
    { 
     someFunction(someClosure: someOtherClosure) 
    } 
} 

但我得到的錯誤:Passing non-escaping parameter 'someOtherClosure' to function expecting an @escaping closure

這兩個閉包實際上都是不可逃避的(默認情況下),並且明確地將@noescape添加到someFunction會產生一個警告,指出這是Swift 3.1中的默認值。

任何想法,爲什麼我得到這個錯誤?

- 更新 - 截圖附: enter image description here

+0

你在哪裏有這個錯誤?任何截圖或更多信息? @escaping –

+0

你沒有在someOtherFunction中調用someOtherClosure(),所以它不應該是一個逃避閉包? Swift不是我的主要語言。 –

+0

@Lu_添加屏幕截圖 – XmasRights

回答

3

前面已經說過,Optional閉包是escaping。另外:

Swift 3.1有一個withoutActuallyEscaping輔助函數,可以在這裏很有用。它標記爲關閉escaping僅用於在傳遞的閉包中使用,因此您不必將escaping屬性暴露給函數簽名。

可以使用這樣的:

extension Array { 

    private func someFunction(someClosure: (() -> Int)?) { 
     someClosure?() 
    } 

    func someOtherFunction(someOtherClosure:() -> Int) { 
     withoutActuallyEscaping(someOtherClosure) { 
      someFunction(someClosure: $0) 
     } 
    } 
} 


let x = [1, 2, 3] 

x.someOtherFunction(someOtherClosure: { return 1 }) 

希望這是有幫助的!

4

可選閉包總是被逃脫。

這是爲什麼?這是因爲可選的(這是一個枚舉)封裝閉包並在內部保存它。

有一篇關於@escapinghere怪癖的優秀文章。

+0

太棒了!謝謝 – XmasRights

0

問題是可選項(在這種情況下是(()-> Int)?)是一個Enum,它捕獲它們的值。如果該值是一個函數,則它必須與@escaping一起使用,因爲它確實被可選項捕獲。 在你的情況下,它會變得棘手,因爲可選項捕獲的閉包自動捕獲另一個閉包。所以someOtherClosure也必須標記爲@escaping

您可以在操場測試下面的代碼,以確認這一點:

extension Array 
{ 
    private func someFunction(someClosure:() -> Int) 
    { 
     // Do Something 
    } 

    func someOtherFunction(someOtherClosure:() -> Int) 
    { 
     someFunction(someClosure: someOtherClosure) 
    } 
} 

let f:()->Int = { return 42 } 

[].someOtherFunction(someOtherClosure: f) 
+1

'Optional'不是不透明的 - 它是'enum'並且是完全透明的。 – Hamish

+1

正如@Hamish所說,可選的是'enum可選 {case some(T),case none}'當你記得這些時候,很多可選項的「怪癖」變得很清晰。 – JeremyP