问题
I have this code in lrvViewModel.swift
func getVerificationID (phoneNumber: String) -> Future<String?, Error> {
return Future<String?, Error> { promise in
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { (verificationID, error) in
if let e = error {
promise(.failure(e))
return
}
print("verification worked")
self.defaults.set(verificationID, forKey: "authVerificationID")
return promise(.success(verificationID))
}
}
}
and then i call and subscribe to the Publisher in another file like this
let _ = lrvViewModel.getVerificationID(phoneNumber: (lrvViewController?.textField.text)!)
.sink(receiveCompletion: {
print("Error worked")
// does a bunch of stuff
}, receiveValue: {
print("completion worked")
// does a bunch of stuff
})
I don't get any buildtime errors, but whenever I run the app the GetVerificationID function runs fine (prints "Verification worked"), but the code within .sink doesn't run (I don't get any print statements). What's going on?
Edit:
My solution was to give up on combine and go back to RXSwift where the code is simply:
var validateObs = PublishSubject<Any>()
func getVerificationID (phoneNumber: String) {
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { (verificationID, error) in
if let e = error {
print("v error")
self.validateObs.onError(e)
return
}
self.defaults.set(verificationID, forKey: "authVerificationID")
self.validateObs.onCompleted()
}
}
and
lrvViewModel.getVerificationID(phoneNumber: (lrvViewController?.textField.text)!)
let _ = lrvViewModel.validateObs.subscribe(onError: {
let e = $0
print(e.localizedDescription)
// do stuff
}, onCompleted: {
// do stuff
})
Was hoping to not rely on a dependency but RxSwift implementation was much easier.
If someone knows the solution to the Combine Future problem please post! I would still like to know wtf is happening. It's very possible (and likely) I'm just using combine wrong.
Edit 2:
Was using combine wrong. I can duplicate the code I had with RXSwift like this:
let verifyPub = PassthroughSubject<Any, Error>()
func getVerificationID (phoneNumber: String) {
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { (verificationID, error) in
if let e = error {
self.verifyPub.send(completion: .failure(e))
return
}
print("verification worked")
self.defaults.set(verificationID, forKey: "authVerificationID")
self.verifyPub.send(completion: .finished)
}
}
and
let subs = Set<AnyCancellable>()
let pub = lrvViewModel.verifyPub
.sink(receiveCompletion: { completion in
if case let .failure(error) = completion {
print("Error worked")
// do stuff
} else {
print("completion worked")
// do stuff
}
}, receiveValue: { _ in
print("this will never happen")
}).store(in: &subs)
I didnt' understand that in combine there are only two results to a sink, a completion or a value, and that completion is split up into multiple cases. Whereas in RxSwift you have OnNext, OnComplete, and OnError.
Shoutout to the book on Combine from raywanderlich.com. Good stuff.
回答1:
What's going on is that your .sink
is not followed by a .store
command, so the pipeline goes out of existence before any value has a chance to come down it.
Your assignment of the pipeline to the empty _
effectively masks the problem. The compiler tried to warn you, and you shut it down.
来源:https://stackoverflow.com/questions/62179405/sink-is-not-returning-the-promise-values-from-a-future-publisher