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