简体   繁体   English

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

[英]Modifying struct instance variables within a Dispatch closure in Swift

I'm using the DEVELOPMENT-SNAPSHOT-2016-06-06-a version of Swift. 我正在使用DEVELOPMENT-SNAPSHOT-2016-06-06-a版本的Swift。 I cannot seem to get around this issue, I've tried using @noescape in various places, but I still have the following error: 我似乎@noescape这个问题,我尝试在各个地方使用@noescape ,但我仍然有以下错误:

Closure cannot implicitly capture a mutating self parameter 闭包不能隐式捕获变异的自身参数

To better explain, here is a simple example: 为了更好地解释,这是一个简单的例子:

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
      }
     }
   }
 }

Something must have changed in these Swift binaries that is now causing my previously working code to break. 这些Swift二进制文件中的某些东西必须已经改变,现在导致我以前工作的代码中断了。 A workaround I want to avoid is making my struct a class, which does help in fixing the issue. 我想避免的一种解决方法是使我的结构体成为一个类,这有助于解决问题。 Let me know if there is another way. 如果还有其他方法,请告诉我。

I cannot test it, because I'm not using a build with that error, but I'm pretty sure by capturing self explicitly you can fix it: 我无法测试它,因为我没有使用的生成与该错误,但我通过捕捉自我明确 ,你可以解决它很肯定:

dispatch_sync(connectQueue) { [self] in
    self.test = 20
}

EDIT: Apparently it doesn't work, maybe you can try this (not very nice tbh): 编辑:显然它不起作用,也许你可以尝试这个(不是很好tbh):

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

If you want to read more on why, here is the responsible Swift proposal . 如果您想了解更多关于原因的信息,请参阅负责的Swift提案

The new dispatch API makes the sync method @noreturn so you wouldn't need the explicit capture: 新的调度API使sync方法@noreturn因此您不需要显式捕获:

connectQueue.sync {
    test = 20
}

You are using Swift3 since you mentioned a recent dev snapshot of Swift . 您正在使用Swift3,因为您提到了最近的Swift dev snapshot Try below and let me know if it works: 请尝试以下操作,让我知道它是否有效:

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
        }
    }
}

If you are interested in other types of queues, check these: 如果您对其他类型的队列感兴趣,请检查以下内容:

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

Get the mainQueue asynchronously and synchronously: 以异步和同步方式获取mainQueue

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

And if you are interested in Background: 如果你对背景感兴趣:

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

You could refer this for new features in Swift3 and for changes to existing version: Migrating to Swift 2.3 or Swift 3 from Swift 2.2 你可以参考这个来获取Swift3中的新功能以及对现有版本的更改: 从Swift 2.2迁移到Swift 2.3或Swift 3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM