2016-05-02 9 views
18

मैं आरएक्सस्विफ्ट के साथ बहुत शुरुआत कर रहा हूं और मैं एक साधारण लॉगिन स्क्रीन से शुरू करने की कोशिश कर रहा हूं। तो मेरे पास 2 टेक्स्ट फ़ील्ड और एक लॉगिन बटन है, जो PublishSubject से जुड़ा हुआ है, इसलिए हर बार जब मैं बटन टैप करता हूं, तो मैं प्रमाणीकरण करने के लिए एक नेटवर्क अनुरोध भेजूंगा।आरएक्सस्विफ्ट - कुछ अवधारणा को गलत तरीके से

चूंकि प्रमाणीकरण विफल हो सकता है, इसलिए मैं Driver के साथ गया, इसलिए जब भी मैं बटन क्लिक करता हूं तो मैं अपना अनुरोध दोबारा चला सकता हूं।

मेरे पास 2 संस्करण है जो मुझे लगता है कि एक ही कोड है लेकिन एक काम करता है और कोई नहीं करता है। मैं समझने की कोशिश कर रहा हूं कि दृश्य के पीछे क्या होता है।

यहाँ पहले संस्करण जो काम करता है (अनुरोध हर बार जब मैं बटन को स्पर्श करें):

let credentials = Observable.combineLatest(email.asObservable(), password.asObservable()) { ($0, $1) } 
self.signIn = signInTaps.asObservable() 
    .withLatestFrom(c) 
    .flatMapLatest { email, password in // returns Observable<AuthenticateResponse> 
     return provider.request(.Authenticate(email: email, password: password)) 
      .filterSuccessfulStatusCodes() 
      .mapObject(AuthenticateResponse) 
    } 
    .map { element -> Result<AuthenticateResponse, APIError> in // returns Observable<Result<AuthenticateResponse, APIError>> 
     return .Success(element) 
    } 
    .asDriver { error in // returns Driver<Result<AuthenticateResponse, APIError>> 
     let e = APIError.fromError(error) 
     return Driver<Result<AuthenticateResponse, APIError>>.just(.Failure(e)) 
    } 
    .debug() 
:

let credentials = Driver.combineLatest(email.asDriver(), password.asDriver()) { ($0, $1) } 
self.signIn = signInTaps 
    .asDriver(onErrorJustReturn:()) 
    .withLatestFrom(credentials) 
    .flatMapLatest { email, password in // returns Driver<Result<AuthenticateResponse, APIError>> 
     return provider.request(.Authenticate(email: email, password: password)) 
      .filterSuccessfulStatusCodes() 
      .mapObject(AuthenticateResponse) 
      .map { element -> Result<AuthenticateResponse, APIError> in 
       return .Success(element) 
      } 
      .asDriver { error in 
       let e = APIError.fromError(error) 
       return Driver<Result<AuthenticateResponse, APIError>>.just(.Failure(e)) 
      } 
      .debug() 
    } 

और यहाँ एक जो (केवल प्रथम क्लिक पर अनुरोध आग) काम नहीं करता है

जानकारी के लिए यहाँ मेरी गुण घोषणा है:

let email = Variable("") 
let password = Variable("") 
let signInTaps = PublishSubject<Void>()  
let signIn: Driver<Result<AuthenticateResponse, APIError>> 
+0

'flatMap' बनाम 'flatMapLatest' https://github.com/baconjs/bacon.js/wiki/Diagrams – onmyway133

उत्तर

11

की क्या happenin है टूट चलो पहले एक में जी (क्योंकि वे प्राय: एक ही हैं):

// 1. 
let credentials = Driver.combineLatest(email.asDriver(), password.asDriver()) { ($0, $1) } 
// 2. 
self.signIn = signInTaps 
    .asDriver(onErrorJustReturn:()) 
    // 3. 
    .withLatestFrom(credentials) 
    // 4. 
    .flatMapLatest { email, password in // returns Driver<Result<AuthenticateResponse, APIError>> 
    return provider.request(.Authenticate(email: email, password: password)) 
     .filterSuccessfulStatusCodes() 
     .mapObject(AuthenticateResponse) 
     .map { element -> Result<AuthenticateResponse, APIError> in 
      return .Success(element) 
     } 
     .asDriver { error in 
      let e = APIError.fromError(error) 
      return Driver<Result<AuthenticateResponse, APIError>>.just(.Failure(e)) 
     } 
     .debug() 
} 
  1. आप email और पासवर्ड से नवीनतम संकेत मेल कर रहे हैं और उन्हें String रों की एक टपल में संयोजन।
  2. यह सिग्नल में आपका संकेत है, निम्नलिखित सभी सिग्नलों का समग्र।
  3. आप एक बटन के टैप के साथ credentials से नवीनतम परिणाम जोड़ रहे हैं।
  4. हर बार जब बटन टैप किया जाता है या ईमेल/पासवर्ड उत्सर्जित होता है, तो आप वर्तमान सिग्नल को रद्द कर रहे हैं और एक नया निर्माण कर रहे हैं जो कॉल (मोया का उपयोग करके) बनाता है, सफल स्थिति कोड द्वारा फ़िल्टर करता है, ऑब्जेक्ट मैपिंग करता है, और सफलतापूर्वक हैंडलिंग करता है और त्रुटि।

दूसरा उदाहरण अधिकतर वही है जो आप ड्राइवरों के बजाय अवलोकनों का उपयोग कर रहे हैं। signInTaps पर जांचें और देखें कि जब भी आप बटन टैप करते हैं तो आप ईवेंट प्राप्त कर रहे हैं या नहीं। यह हो सकता है कि सिग्नल डिलीकेटिंग लाइन के नीचे कहीं और वास्तव में दोनों संस्करणों के बीच एकमात्र अंतर ड्राइवरों और अवलोकनों का उपयोग है।

यह भी ध्यान रखें कि ड्राइवर का उपयोग केवल एक सिंटेक्टिक चीनी पर एक अवलोकन योग्य है।

let intDriver = sequenceOf(1, 2, 3, 4, 5, 6) 
.asDriver(onErrorJustReturn: 1) 
.map { $0 + 1 } 
.filter { $0 < 5 } 

तो जब आप ड्राइवरों से अधिक observables उपयोग करते हैं, आप .observeOn और shareReplay खो रहे हैं के रूप में

let intObservable = sequenceOf(1, 2, 3, 4, 5, 6) 
.observeOn(MainScheduler.sharedInstance) 
.catchErrorJustReturn(1) 
.map { $0 + 1 } 
.filter { $0 < 5 } 
.shareReplay(1) 

में ही है। यह हो सकता है कि ड्राइवरों के साथ आप केवल रीप्ले और कैश किए गए मान देख रहे हों।

+0

लेकिन सभी UIKit सिग्नल वे" हॉट अवलोकन योग्य "नहीं हैं? मेरा मतलब है, क्या वे हर समय उत्सर्जित हो रहे हैं और कभी भी बर्बाद नहीं हो रहे हैं? – Yaman

+0

इसके अलावा, मेरे दूसरे उदाहरण में मैंने सभी चीज़ों को 'चालक' को सैद्धांतिक रूप से डाला, इसलिए सैद्धांतिक रूप से सिग्नल को कभी भी हटाया नहीं जाना चाहिए? – Yaman

+0

आपका साइनइन टैप अवलोकन योग्य नहीं हो सकता है, यही कारण है कि यह केवल एक बार आग लग सकता है। मैं RXSwift पर ReactiveCocoa का उपयोग करना चाहता हूं, समझने में बहुत आसान है। – barndog

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