甚至在我的操作在 main 方法中完成之前,完成块就会被触发



我正在尝试使用OperationQueue和Operation在Firebase中创建用户。我将 Firebase 身份验证调用置于操作主方法中。甚至在 Firebase 注册过程成功之前,操作的完成块就会被触发。

注册视图模式.swift

//This is operation initialization
let operationQueues = OperationQueues()
let registrationRecord = RegistrationRecord(user: self.user!, encryptedData: self.fireBaseAuthCompliance)
let userRegistrationOperation = UserRegistrationOperation(registrationRecord: registrationRecord)
userRegistrationOperation.completionBlock = {
//I am expecting this completion block will be called only when my firebase invocation in main() method is finished
DispatchQueue.main.async {
//Since this block is getting triggered even before completion, the //value is returning as null
self.user?.uid = userRegistrationOperation.registrationRecord.user.uid
}
}
operationQueues.userRegistrationQueue.addOperation(userRegistrationOperation)

用户注册操作.swift

class OperationQueues {
lazy var userRegistrationQueue: OperationQueue = {
var queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
queue.name = "User registration queue"
return queue
}()
}
class UserRegistrationOperation: Operation {
var registrationRecord: RegistrationRecord
init(registrationRecord: RegistrationRecord) {
self.registrationRecord = registrationRecord
}
override func main() {
guard !isCancelled else { return }
self.registrationRecord.state = RegistrationStatus.pending
//Firebase invocation to create a user in Firebase Auth
Auth.auth().createUser(withEmail: self.registrationRecord.user.userEmail, password: self.registrationRecord.encryptedData){ [weak self](result, error) in
if error != nil {
print("Error occured while user registration process")
self?.registrationRecord.state = RegistrationStatus.failed
return
}
self?.registrationRecord.user.uid = result?.user.uid
self?.registrationRecord.state = RegistrationStatus.processed
}
}
}

问题是您的操作正在启动异步进程,但操作在异步任务启动时完成,而不是在异步任务完成时完成。

您需要执行与"并发"操作关联的 KVO,如文档中所述:

如果要创建并发操作,则至少需要重写以下方法和属性:

  • start()
  • isAsynchronous
  • isExecuting
  • isFinished

在并发操作中,start()方法负责以异步方式启动操作。无论是生成线程还是调用异步函数,都可以从此方法执行。启动操作后,start()方法还应更新isExecuting属性报告的操作的执行状态。为此,您可以发送isExecuting密钥路径的 KVO 通知,让感兴趣的客户端知道操作现在正在运行。isExecuting属性还必须以线程安全的方式提供状态。

完成或取消其任务后,并发操作对象必须为isExecutingisFinished密钥路径生成 KVO 通知,以标记操作的最终状态更改。(在取消的情况下,即使操作未完全完成其任务,更新isFinished密钥路径仍然很重要。排队操作必须报告它们已完成,然后才能从队列中删除。除了生成 KVO 通知外,isExecutingisFinished属性的替代还应继续根据操作状态报告准确的值。

现在所有这些听起来都很有趣,但实际上并没有那么糟糕。一种方法是编写一个基操作类来处理所有这些 KVO 内容,这个答案概述了一个示例实现。

然后你可以改用子类AsynchronousOperation,并确保在任务完成时调用finish(或任何触发isFinishedKVO(的内容:

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,这只是一个例子。但是,一旦你有一个很好地封装并发操作 KVO 的类,你就可以对它进行子类化,你可以编写自己的并发操作,只需对代码进行很少的更改。

相关内容

最新更新