2017-02-16 9 views
13

मैंने कई अवलोकनों की श्रृंखला के साथ फ़ंक्शन नीचे बनाया है, हालांकि जो कुछ भी मैं करता हूं वह completed पर कॉल नहीं करता है? यह केवल निम्नलिखित वापसी:flatMap चालू नहीं हो रहा है

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

भले ही जब मैं observables व्यक्तिगत रूप से 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() 
    }) 
} 

fetchProfileData

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() 
    }) 


} 

observerFacebook

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

     return FacebookProvider(parentController: self) 
    } 
}() 
+1

अच्छा लग रहा है। क्या आप rx_authenticate और fetchProfileData कार्यान्वयन जोड़ सकते हैं? – ULazdins

+0

अब यह जोड़ा गया है। अग्रिम में धन्यवाद –

+1

क्या आप 'पर्यवेक्षकफ़ेसबुक' के लिए परिभाषा भी जोड़ सकते हैं? – tomahh

उत्तर

5

जो एक नमूदार है कि मूल्यों हर facebookButton उपयोग किया जाता है उत्सर्जित करेगा रिटर्न observerFacebook बुला, साथ श्रृंखला शुरू होता है।

यह अवलोकन केवल तभी पूरा होगा जब facebookButton जारी हो जाए, संभवतः जब दृश्य नियंत्रक इसे स्क्रीन से हटा दिया जाता है।

शेष श्रृंखला map या flatMap होगी, लेकिन पूरा होने पर कभी बल नहीं डालें क्योंकि एक और टैप पूरी श्रृंखला को फिर से ट्रिगर करेगा।

आसान इस को हल करने के facebookButton.rx.tap पर take(1) के लिए एक कॉल को जोड़ने के लिए है, ताकि समारोह इतना की तरह परिभाषित किया जाएगा, वे जिस तरह से:

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

अब, observerFacebookहोगा पहले के बाद पूरा हो गया टैप करें और आपको onCompleted पर कॉल देखना चाहिए।

ध्यान दें कि आप त्रुटियों पर श्रृंखला लिए पुन: सदस्यता के लिए यदि आप जब एक और नल में आता है इसे फिर से करना चाहते आवश्यकता होगी।

+0

यदि कोई और यहां rxjava उत्तरों की तलाश में है, तो मैं जिस मूर्खता का उपयोग करता हूं वह 'Observable.create (s -> { s.onNext (नया ऑब्जेक्ट()); emitter = s;})। flatMap ($ -> realObservable) 'और फिर' emitter.onComplete() 'ग्राहक को 'पूर्ण()' को प्रचारित करेगा। –

संबंधित मुद्दे