4

在 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]

如何修改闭包内的原始变量 ()?

更新:

实际上,我有一个解决方法来处理这种情况,方法是将数组放入一个对象中,这样我就可以通过引用将该对象传递给函数,我们可以在函数内部修改相同的数组实例。但我想看看有什么聪明的方法来存档

4

1 回答 1

2

要从您需要的闭包中获得变量转义@escaping,请查看内容。一种解决方法是将完成函数作为参数而不是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)")

注意:上面的示例适用于 Swift 3,其中inout不允许在闭包中捕获参数。根据您的帖子,您可能正在使用较低版本的 Swift,inout而不是设置列表的可变副本:var list = list。但是,逻辑非常相似。

有关更多信息,请查看在 Swift 进化中将 inout 捕获限制为 @noescape 上下文:

Swift 在闭包捕获inout参数并转义其封闭上下文时的行为是常见的混淆来源。inout除了@noescape 闭包,我们应该禁止隐式捕获参数。

于 2017-07-28T06:56:23.640 回答