Ответ
Для создания асинхронной операции необходимо создать подкласс Operation и вручную управлять его состояниями (isExecuting, isFinished), так как стандартная Operation по умолчанию синхронна.
Ключевые шаги:
- Переопределить
isAsynchronousдля возвратаtrue. - Вручную управлять KVO-свойствами
isExecutingиisFinishedс потокобезопасностью. - Переопределить
start(), чтобы запустить асинхронную задачу и изменить состояние. - По завершении задачи вызвать метод, который установит
isExecuting = falseиisFinished = true.
Пример реализации потокобезопасной асинхронной операции:
class AsyncOperation: Operation {
// Используем приватную очередь для потокобезопасного доступа к состояниям
private let stateQueue = DispatchQueue(label: "com.example.asyncoperation.state", attributes: .concurrent)
override var isAsynchronous: Bool { return true }
private var _isExecuting = false
override private(set) var isExecuting: Bool {
get { return stateQueue.sync { _isExecuting } }
set {
willChangeValue(forKey: "isExecuting")
stateQueue.sync(flags: .barrier) { _isExecuting = newValue }
didChangeValue(forKey: "isExecuting")
}
}
private var _isFinished = false
override private(set) var isFinished: Bool {
get { return stateQueue.sync { _isFinished } }
set {
willChangeValue(forKey: "isFinished")
stateQueue.sync(flags: .barrier) { _isFinished = newValue }
didChangeValue(forKey: "isFinished")
}
}
override func start() {
// Проверяем, не отменена ли операция до старта
if isCancelled {
finish()
return
}
isExecuting = true
main()
}
override func main() {
// Запускаем асинхронную работу (например, сетевой запрос)
DispatchQueue.global().async {
// Имитация работы
sleep(2)
// По завершении ОБЯЗАТЕЛЬНО вызываем finish
self.finish()
}
}
func finish() {
// Корректно завершаем состояния операции
isExecuting = false
isFinished = true
}
}
// Использование
let queue = OperationQueue()
queue.addOperation(AsyncOperation())
Почему это важно: Без правильного управления состояниями OperationQueue не узнает, когда операция завершилась, и не сможет запустить следующие операции в очереди.