Подтвердить что ты не робот

Изменение переменных экземпляра struct внутри закрытия отправки в Swift

Я использую версию Swift DEVELOPMENT-SNAPSHOT-2016-06-06-a. Я не могу обойти эту проблему, я пытался использовать @noescape в разных местах, но у меня все еще есть следующая ошибка:

Закрытие не может неявно захватывать параметр mutating self

Чтобы лучше объяснить, вот простой пример:

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, которые теперь приводят к разрыву моего предыдущего рабочего кода. Обходной путь, который я хочу избежать, делает мою структуру классом, что помогает в устранении проблемы. Дайте мне знать, есть ли другой способ.

4b9b3361

Ответ 1

Я не могу его протестировать, потому что я не использую сборку с этой ошибкой, но я уверен, захватив ящик явно, вы можете это исправить:

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

EDIT: По-видимому, это не сработает, возможно, вы можете попробовать это (не очень приятно tbh):

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

Если вы хотите узнать больше о том, почему это ответственное предложение Swift.

Новый API-интерфейс отправки делает метод sync @noreturn, поэтому вам не понадобится явный захват:

connectQueue.sync {
    test = 20
}

Ответ 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
}

И если вас интересует Background:

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

Вы можете ссылаться на новые функции в Swift3 и на изменения существующей версии: Переход к Swift 2.3 или Swift 3 из Swift 2.2