Проблема заключается в том, что ваша операция инициирует асинхронный процесс, но операция завершается при запуске асинхронной задачи, а не при завершении асинхронной задачи.
Необходимо выполнить KVO, связанный с «одновременным”, Как описано в документации :
Если вы создаете параллельную операцию, вам необходимо как минимум переопределить следующие методы и свойства:
start()
isAsynchronous
isExecuting
isFinished
В параллельной операции ваш *Метод 1024 * отвечает за запуск операции в асинхронном режиме. Независимо от того, порождаете ли вы поток или вызываете асинхронную функцию, вы делаете это из этого метода. После запуска операции ваш метод start()
также должен обновить состояние выполнения операции, сообщаемое свойством isExecuting
. Вы делаете это, отправляя уведомления KVO по ключевому пути isExecuting
, который позволяет заинтересованным клиентам узнать, что операция сейчас выполняется. Ваше свойство isExecuting
также должно предоставлять состояние в поточно-ориентированном режиме.
После завершения или отмены своей задачи объект параллельной операции должен генерировать уведомления KVO для ключа isExecuting
и isFinished
. пути, чтобы отметить окончательное изменение состояния для вашей операции. (В случае отмены все еще важно обновить путь ключа isFinished
, даже если операция не полностью завершила свою задачу. Операции в очереди должны сообщить о том, что они завершены, прежде чем их можно будет удалить из очереди.) ВВ дополнение к генерации уведомлений KVO ваши переопределения свойств isExecuting
и isFinished
также должны продолжать сообщать точные значения, основанные на состоянии вашей операции.
Теперь все это звучит довольно странно,но это на самом деле не так уж и плохо. Один из способов - написать базовый класс операций, который позаботится обо всех этих вещах KVO, и в этом ответе приведен пример реализации .
Тогда вы можете вместо этого создать подкласс AsynchronousOperation
иОбязательно вызовите finish
(или что-либо еще, что вызывает isFinished
KVO), когда задача будет выполнена:
class UserRegistrationOperation: AsynchronousOperation {
var registrationRecord: RegistrationRecord
init(registrationRecord: RegistrationRecord) {
self.registrationRecord = registrationRecord
super.init() // whenever you subclass, remember to call `super`
}
override func main() {
self.registrationRecord.state = .pending
//Firebase invocation to create a user in Firebase Auth
Auth.auth().createUser(withEmail: registrationRecord.user.userEmail, password: registrationRecord.encryptedData) { [weak self] result, error in
defer { self?.finish() } // make sure to call `finish` regardless of how we leave this closure
guard let result = result, error == nil else {
print("Error occured while user registration process")
self?.registrationRecord.state = .failed
return
}
self?.registrationRecord.user.uid = result.user.uid
self?.registrationRecord.state = .processed
}
}
}
Существует множество способов реализовать этот класс AsynchronousOperation
и this это только один пример. Но как только у вас есть класс, который хорошо инкапсулирует параллельную операцию KVO, вы можете создать его подкласс и написать свои собственные параллельные операции с очень небольшими изменениями в вашем коде.