13

我创建了下面的函数,链接了多个可观察对象,但是无论我做什么,它似乎都没有调用completed?它只返回以下内容:

(facebookSignInAndFetchData()) -> subscribed
(facebookSignInAndFetchData()) -> Event next(())

即使当我debug单独观察它们时它们都返回completed

这是我的链接功能

func facebookSignInAndFetchData() {


    observerFacebook.flatMap { (provider: FacebookProvider) in
        return provider.login()
        }.flatMap { token in
            return self.loginViewModel.rx_authenticate(token: token)
        }.flatMap {
            return self.loginViewModel.fetchProfileData()
        }.debug().subscribe(onError: { error in

            //Guard unknown ErrorType
            guard let err = error as? AuthError else {
                //Unknown error message
                self.alertHelper.presentAlert(L10n.unknown)
                return
            }

            //error message handling
            switch err {
            case .notLoggedIn:
                print("not logged in")
                break
            default:
                self.alertHelper.presentAlert(err.description)
            }

        }, onCompleted: {
            self.goToInitialController()
        }).addDisposableTo(self.disposeBag)

}

rx_authenticate

func rx_authenticate(token: String) -> Observable<Void> {


    return Observable.create({ observer in
        let credentials = SyncCredentials.facebook(token: token)
        SyncUser.logIn(with: credentials, server: URL(string: Globals.serverURL)!, onCompletion: { user, error in

            //Error while authenticating
            guard error == nil else {
                print("error while authenticating: \(error!)")
                observer.onError(AuthError.unknown)
                return
            }

            //Error while parsing user
            guard let responseUser = user else {
                print("error while authenticating: \(error!)")
                observer.onError(AuthError.unknown)
                return
            }

            //Authenticated
            setDefaultRealmConfiguration(with: responseUser)

            //next
            observer.onNext()

            //completed
            observer.onCompleted()


        })

        return Disposables.create()
    })
}

获取配置文件数据

func fetchProfileData() -> Observable<Void> {

     return Observable.create({ observer in

        //Fetch facebookData
        let params = ["fields" : "name, picture.width(480)"]
        let graphRequest = GraphRequest(graphPath: "me", parameters: params)
        graphRequest.start {
            (urlResponse, requestResult) in
            switch requestResult {
            case .failed(_):
                //Network error
                observer.onError(AuthError.noConnection)
                break
            case .success(let graphResponse):

                if let responseDictionary = graphResponse.dictionaryValue {

                    guard let identity = SyncUser.current?.identity else {
                        //User not logged in
                        observer.onError(AuthError.noUserIdentity)
                        return
                    }

                    //Name
                    let name = responseDictionary["name"] as! String

                    //Image dictionary
                    let pictureDic = responseDictionary["picture"] as! [String: Any]
                    let dataDic = pictureDic["data"] as! [String: Any]
                    let imageHeight = dataDic["height"] as! Int
                    let imageWidth = dataDic["width"] as! Int
                    let url = dataDic["url"] as! String

                    //Create Person object
                    let loggedUser = Person()
                    loggedUser.id = identity
                    loggedUser.name = name

                    //Create photo object
                    let photo = Photo()
                    photo.height = imageHeight
                    photo.width = imageWidth
                    photo.url = url

                    //Append photo object to person object
                    loggedUser.profileImage = photo

                    //Save userData
                    let realm = try! Realm()
                    try! realm.write {
                        realm.add(loggedUser, update: true)
                    }

                    //next
                    observer.onNext()

                    //completed
                    observer.onCompleted()

                } else {
                    //Could not retrieve responseData
                    observer.onError(AuthError.noResponse)
                }
            }
        }



        return Disposables.create()
    })


}

观察者脸书

//FacebookProvider
private lazy var observerFacebook: Observable<FacebookProvider>! = {
    self.facebookButton.rx.tap.map {

        return FacebookProvider(parentController: self)
    }
}()
4

1 回答 1

7

该链以 call 开始observerFacebook,它返回一个 observable,每次facebookButton被点击时都会发出值。

这个 observable 只有在facebookButton被释放时才会完成,很可能是当持有它的视图控制器从屏幕上移除时。

链的其余部分将mapflatMap,但永远不会强制完成,因为另一个点击将再次触发整个链。

解决这个问题的简单方法是添加对take(1)on的调用facebookButton.rx.tap,以便函数定义如下:

private lazy var observerFacebook: Observable<FacebookProvider>! = {
    self.facebookButton.rx.tap
    .take(1)
    .map {
        return FacebookProvider(parentController: self)
    }
}()

现在,observerFacebook 在第一次点击后完成,您应该会看到对onCompleted.

请注意,如果您想在另一个点击进入时再次执行它,您需要重新订阅错误链。

于 2017-02-19T09:07:44.900 回答