在Swift的Dispatch闭包中修改struct实例变量

时间:2016-06-27 15:51:03

标签: swift struct grand-central-dispatch

我正在使用Swift的DEVELOPMENT-SNAPSHOT-2016-06-06-a版本。我似乎无法绕过这个问题,我尝试在各个地方使用@noescape,但我仍然有以下错误:

  

Closure不能隐式捕获变异的自身参数

为了更好地解释,这是一个简单的例子:

public struct ExampleStruct {
  let connectQueue = dispatch_queue_create("connectQueue", nil)
  var test = 10

  mutating func example() {
    if let connectQueue = self.connectQueue {
      dispatch_sync(connectQueue) {
        self.test = 20 // error happens here
      }
     }
   }
 }

这些Swift二进制文件中的某些东西必定已经改变,现在导致我以前工作的代码中断了。我想避免的一种解决方法是使我的结构体成为一个类,这有助于解决问题。如果还有其他方法,请告诉我。

2 个答案:

答案 0 :(得分:11)

我无法测试它,因为我没有使用带有该错误的构建版本,但我非常确定通过显式捕获 你可以修复它:

dispatch_sync(connectQueue) { [self] in
    self.test = 20
}
编辑:显然它不起作用,也许你可以试试这个(不是很好):

var copy = self
dispatch_sync(connectQueue) {
    copy.test = 20
}
self = copy

如果您想详细了解原因,here is the responsible Swift proposal

新的调度API会生成sync方法@noreturn,因此您无需显式捕获:

connectQueue.sync {
    test = 20
}

答案 1 :(得分:2)

您使用的是Swift3,因为您提到了最新的dev snapshot Swift。请尝试以下操作并告诉我它是否有效:

public struct ExampleStruct {
    let connectQueue = DispatchQueue(label: "connectQueue", attributes: .concurrent)//This creates a concurrent Queue

    var test = 10

    mutating func example() {
        connectQueue.sync { 
            self.test = 20
        }
    }
}

如果您对其他类型的队列感兴趣,请查看以下内容:

let serialQueue = DispatchQueue(label: "YOUR_QUEUE", attributes: .serial)
serialQueue.sync { 
    //
}

以异步和同步方式获取mainQueue

DispatchQueue.main.async {
   //async operations
}
DispatchQueue.main.sync {
    //sync operations
}

如果您对背景感兴趣:

DispatchQueue.global(attributes: .qosDefault).async {
  //async operations
}

您可以将此功能引用到Swift3中的新功能以及对现有版本的更改:Migrating to Swift 2.3 or Swift 3 from Swift 2.2