I am trying to create user in firebase using OperationQueue and Operation. I placed the Firebase Auth call in operation main method. Completion block of the operation is getting triggered even before firebase registration process is succeeded.
RegistrationViewModal.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)
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
}
}
}
The problem is that your operation is initiating an asynchronous process, but the operation finishes when the asynchronous task is started, not when the asynchronous task finishes.
You need to do the KVO associated with a “concurrent” operation, as outlined in the documentation:
Now all of that sounds quite hairy, but it’s actually not that bad. One way is to write a base operation class that takes care of all of this KVO stuff, and this this answer outlines one example implementation.
Then you can subclass
AsynchronousOperationinstead, and make sure to callfinish(or whatever triggers theisFinishedKVO) when the task is done:There are lots of ways to implement that
AsynchronousOperationclass and this is just one example. But once you have a class that nicely encapsulates the concurrent operation KVO, you can subclass it and you can write your own concurrent operations with very little changes to your code.