2017-07-28 56 views
3

在Swift集合默認傳值,我們可以使用inout使它在函數參數中通過引用傳遞,但我們如何在閉包捕獲變量中做到這一點?通過引用快速關閉捕獲數組

var list = [1, 2, 3] 
func edit(inout list: [Int]) { 
    list.append(4) 
    dispatch_async(dispatch_get_main_queue()) { 
     list.append(5) 
    } 
} 
edit(&list) 
...// after dispatch_async was executed 
NSLog("\(list)") 

結果將是[1,2,3,4]

如何修改內部閉合原始變量()?

UPDATE:

其實我有一種解決方法通過將陣列到一個對象來處理這種情況,所以我可以通過引用傳遞該對象的函數,我們可以修改函數內的同一陣列實例。但我希望看到任何聰明的方法來存檔,

回答

2

爲了從封閉變量轉義你需要@escaping,檢查this了。解決方法是將完成功能作爲參數,而不是inout變量。

class MyClass { 
    static func edit(_ list: [Int], _ completion: @escaping ([Int]) ->()) { 
     var list = list 
     list.append(4) 
     DispatchQueue.main.async() { 
      list.append(5) 
      completion(list) 
     } 
    } 
} 

var myList = [1, 2, 3] 
MyClass.edit(myList) { (list) in 
    myList = list 
    print("My list after editing: \(myList)") 
} 
print("My list without editing: \(myList)") 

:上面的示例是用於夫特3,其中inout參數不允許在封閉件被捕獲。根據您的文章,您可能會使用較低版本的Swift,您可能可以使用inout而不是設置列表的可變副本var list = list。但是,邏輯非常相似。

欲瞭解更多信息,請查看Limiting inout capture to @noescape contexts在斯威夫特進化:

時關閉捕捉inout參數和逃避 及其外圍方面斯威夫特的行爲是混亂的常見原因。我們應該 禁止隱含捕獲inout參數,但在@noescape 關閉。

+0

感謝您的回覆,但有沒有機會實現它,而無需訪問函數內的任何實例變量?你可以把它當作一個靜態函數 – Alan

+0

是的,我根據你的需要編輯我的答案。 – Lawliet

+0

謝謝,你的答案是一種獲取數組的新副本的方法,我們可以在完成閉包中更新實例數組變量。但我想知道任何在傳入函數後「直接」修改原始數組的機會。對於我在這個問題上的不好解釋抱歉。我試過你的代碼,全局'list'變量的結果仍然是[1,2,3] – Alan