.sink is not returning the promise values from a Future Publisher

岁酱吖の 提交于 2020-11-29 21:27:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!