खोज…


RxSwift मूल बातें

FRP, या फंक्शनल रिएक्टिव प्रोग्रामिंग, के कुछ मूल शब्द हैं जिन्हें आपको जानना आवश्यक है।

डेटा के प्रत्येक टुकड़े को Observable रूप में दर्शाया जा सकता है, जो एक अतुल्यकालिक डेटा स्ट्रीम है। एफआरपी की शक्ति स्ट्रीम, Observable एस के रूप में तुल्यकालिक और अतुल्यकालिक घटनाओं का प्रतिनिधित्व करती है, और इसके साथ काम करने के लिए समान इंटरफ़ेस प्रदान करती है।

आमतौर पर Observable कई (या कोई नहीं) घटनाओं को धारण करता है जो दिनांक रखती है। .Next इवेंट्स, और फिर इसे सफलतापूर्वक (। .Success ) या एक त्रुटि ( .Error ) के साथ समाप्त किया जा सकता है।

चलो निम्नलिखित संगमरमर आरेख पर एक नज़र डालें:

--(1)--(2)--(3)|-->

इस उदाहरण में Int मानों की एक धारा है। जैसे-जैसे समय आगे बढ़ता है, तीन .Next घटनाएँ हुईं, और फिर धारा सफलतापूर्वक समाप्त हो गई।

--X->

शो ऊपर चित्र एक मामले में जहां कोई डेटा उत्सर्जित किया गया था और .Error घटना समाप्त हो जाता है Observable

इससे पहले कि हम आगे बढ़ें, कुछ उपयोगी संसाधन हैं:

  1. RxSwift । उदाहरण देखें, डॉक्स पढ़ें और शुरुआत करें।
  2. RxSwift स्लैक रूम में शिक्षा समस्या के समाधान के लिए कुछ चैनल हैं।
  3. ऑपरेटर क्या करता है, यह जानने के लिए RxMarbles के साथ खेलें और जो आपके मामले में सबसे उपयोगी है।
  4. इस उदाहरण पर एक नज़र डालें, अपने आप कोड का अन्वेषण करें।

वेधशालाएँ बनाना

RxSwift एक बनाने के लिए कई तरीके प्रदान करता Observable , चलो एक नज़र डालें:

import RxSwift

let intObservale = Observable.just(123) // Observable<Int>
let stringObservale = Observable.just("RxSwift") // Observable<String>
let doubleObservale = Observable.just(3.14) // Observable<Double>

तो, वेधशालाएँ बनाई जाती हैं। वे सिर्फ एक मूल्य रखते हैं और फिर सफलता के साथ समाप्त हो जाते हैं। बावजूद इसके बनने के बाद कुछ नहीं हुआ। क्यों?

Observable s के साथ काम करने में दो चरण हैं: आप एक स्ट्रीम बनाने के लिए कुछ का निरीक्षण करते हैं और फिर आप स्ट्रीम की सदस्यता लेते हैं या इसके साथ सहभागिता करने के लिए इसे किसी चीज़ से बाँधते हैं

Observable.just(12).subscribe {
    print($0)
}

कंसोल प्रिंट होगा:

.Next(12)
.Completed()

और अगर मैं केवल डेटा के साथ काम करने में दिलचस्पी रखता हूं, जो कि .Next ईवेंट्स में होता है, तो मैं subscribeNext ऑपरेटर का उपयोग करूंगा:

Observable.just(12).subscribeNext {
    print($0) // prints "12" now
}

यदि मैं कई मानों का पालन करना चाहता हूं, तो मैं विभिन्न ऑपरेटरों का उपयोग करता हूं:

Observable.of(1,2,3,4,5).subscribeNext {
    print($0)
}
// 1
// 2
// 3
// 4
// 5

// I can represent existing data types as Observables also:
[1,2,3,4,5].asObservable().subscribeNext { 
    print($0) 
}
// result is the same as before.

और अंत में, शायद मैं एक Observable चाहता हूं जो कुछ काम करता है। उदाहरण के लिए, Observable<SomeResultType> में नेटवर्क ऑपरेशन को लपेटना सुविधाजनक है। आइए एक नजर डालते हैं इसे हासिल करने की:

Observable.create { observer in    // create an Observable ...
    MyNetworkService.doSomeWorkWithCompletion { (result, error) in
        if let e = error {
            observer.onError(e)    // ..that either holds an error
        } else {
            observer.onNext(result) // ..or emits the data
            observer.onCompleted()  // ..and terminates successfully.
        }
    }
    return NopDisposable.instance // here you can manually free any resources
                                //in case if this observable is being disposed.
}

निपटान

सदस्यता बनाए जाने के बाद, इसके सही निपटारे का प्रबंधन करना महत्वपूर्ण है।

डॉक्स ने हमें बताया कि

यदि कोई अनुक्रम परिमित समय में समाप्त हो जाता है, तो कॉल को डिस्पोज़ नहीं करना या एडडिसोप्रोटेक्टो (डिस्पोज़बाग) का उपयोग नहीं करना, किसी भी स्थायी संसाधन लीक का कारण नहीं होगा। हालांकि, उन संसाधनों का उपयोग तब तक किया जाएगा जब तक कि अनुक्रम पूरा नहीं हो जाता है, या तो तत्वों का उत्पादन खत्म करके या एक त्रुटि लौटाता है।

डीललॉकेट संसाधनों के दो तरीके हैं।

  1. disposeBag एस और addDisposableTo ऑपरेटर का उपयोग करना।
  2. takeUntil ऑपरेटर का उपयोग करना।

पहले मामले में आप मैन्युअल रूप से सदस्यता को DisposeBag ऑब्जेक्ट पर पास करते हैं, जो सभी ली गई मेमोरी को सही ढंग से साफ़ करता है।

let bag = DisposeBag()
Observable.just(1).subscribeNext { 
    print($0)
}.addDisposableTo(bag)

आपको वास्तव में हर वर्ग में DisposeBag बनाने की आवश्यकता नहीं है, जो आप बनाते हैं, बस RxSwift समुदाय की NSObject + Rx नामक परियोजना पर एक नज़र डालें। ऊपर दिए गए कोड को फ्रेमवर्क का उपयोग करके निम्नानुसार फिर से लिखा जा सकता है:

Observable.just(1).subscribeNext { 
    print($0)
}.addDisposableTo(rx_disposeBag)

दूसरे मामले में, यदि सदस्यता का समय self वस्तु जीवनकाल के साथ मेल खाता है, तो takeUntil(rx_deallocated) का उपयोग करके takeUntil(rx_deallocated) को लागू करना संभव है:

let _ = sequence
    .takeUntil(rx_deallocated)
    .subscribe {
        print($0)
    }

बाइंडिंग

Observable.combineLatest(firstName.rx_text, lastName.rx_text) { $0 + " " + $1 }
.map { "Greetings, \($0)" }
.bindTo(greetingLabel.rx_text)

का उपयोग करते हुए combineLatest ऑपरेटर हर बार एक आइटम दो में से किसी द्वारा उत्सर्जित होता है Observables , नवीनतम आइटम प्रत्येक द्वारा उत्सर्जित गठबंधन Observable । तो इस तरह हम दो UITextField के परिणाम को "Greetings, \($0)" टेक्स्ट के साथ एक नया संदेश बनाने के लिए जोड़ते हैं, जो स्ट्रिंग इंटरपोलेशन का उपयोग करके बाद में एक UILabel के पाठ में बाँधते हैं।

हम किसी भी UITableView और UICollectionView डेटा को बहुत आसान तरीके से बांध सकते हैं:

viewModel
.rows
.bindTo(resultsTableView.rx_itemsWithCellIdentifier("WikipediaSearchCell", cellType: WikipediaSearchCell.self)) { (_, viewModel, cell) in
    cell.title = viewModel.title
    cell.url = viewModel.url
}
.addDisposableTo(disposeBag)

कि एक Rx आवरण के चारों ओर cellForRowAtIndexPath डेटा स्रोत विधि। और Rx numberOfRowsAtIndexPath के कार्यान्वयन का भी ध्यान रखता है numberOfRowsAtIndexPath , जो कि पारंपरिक अर्थों में एक आवश्यक विधि है, लेकिन आपको इसे यहाँ लागू करने की आवश्यकता नहीं है, इसका ध्यान रखा जाता है।

RxCocoa और ControlEvents

RxSwift न केवल आपके डेटा को नियंत्रित करने के तरीके प्रदान करता है, बल्कि प्रतिक्रियात्मक तरीके से उपयोगकर्ता कार्यों का प्रतिनिधित्व भी करता है।

RxCocoa में वह सब कुछ होता है जो आपको चाहिए। यह UI के अधिकांश गुणों को Observable s में लपेटता है, लेकिन वास्तव में नहीं। कुछ उन्नत Observable एस कहे जाते हैं जिन्हें ControlEvent s (जो घटनाओं का प्रतिनिधित्व करते हैं) और ControlProperties (जो गुणों का प्रतिनिधित्व करते हैं, आश्चर्य!)। ये चीजें हूड के तहत Observable धाराएं रखती हैं, लेकिन कुछ बारीकियां भी हैं:

  • यह कभी असफल नहीं होता, इसलिए कोई त्रुटि नहीं।
  • यह निपटाया जा रहा नियंत्रण पर Complete अनुक्रम होगा।
  • यह मुख्य थ्रेड ( MainScheduler.instance ) पर घटनाओं को वितरित करता है।

मूल रूप से, आप हमेशा की तरह उनके साथ काम कर सकते हैं:

button.rx_tap.subscribeNext { _ in   // control event
    print("User tapped the button!")
}.addDisposableTo(bag)

textField.rx_text.subscribeNext { text in // control property
    print("The textfield contains: \(text)")
}.addDisposableTo(bag)
// notice that ControlProperty generates .Next event on subscription
// In this case, the log will display 
// "The textfield contains: "
// at the very start of the app.

यह उपयोग करना बहुत महत्वपूर्ण है: जब तक आप Rx का उपयोग करते हैं, @IBAction सामान के बारे में भूल जाते हैं, आपको जो कुछ भी चाहिए वह सब आप एक बार में बाँध और कॉन्फ़िगर कर सकते हैं। उदाहरण के लिए, यूआई-घटक कैसे काम करते हैं, इसका वर्णन करने के लिए आपके व्यू कंट्रोलर का viewDidLoad विधि एक अच्छा उम्मीदवार है।

ठीक है, एक और उदाहरण: मान लीजिए कि हमारे पास एक टेक्स्टफील्ड, एक बटन और एक लेबल है। जब हम बटन पर टैप करते हैं, तो हम टेक्स्टफील्ड में टेक्स्ट को वेरिफाई करना चाहते हैं, और लेबल में परिणाम प्रदर्शित करते हैं। हाँ, एक और मान्य-ईमेल कार्य की तरह लगता है, हुह?

सबसे पहले, हम button.rx_tap पकड़ो button.rx_tap :

----()-----------------------()----->

यहां खाली कोष्ठक उपयोगकर्ता नल दिखाते हैं। इसके बाद, हम ले लेते हैं जो withLatestFrom ऑपरेटर के साथ लिखा गया है ( यहां पर एक नज़र डालें, कल्पना करें कि ऊपरी धारा उपयोगकर्ता नल का प्रतिनिधित्व करती है, नीचे पाठ क्षेत्र में पाठ का प्रतिनिधित्व करता है)।

button.rx_tap.withLatestFrom(textField.rx_text)

----("")--------------------("123")--->
//  ^ tap   ^ i wrote 123    ^ tap

अच्छा, हमारे पास मान्य करने के लिए स्ट्रिंग्स की एक धारा है, केवल तभी उत्सर्जित की जाती है जब हमें सत्यापन करने की आवश्यकता होती है।

किसी भी Observable पास map या filter जैसे परिचित ऑपरेटर होते हैं, हम पाठ को मान्य करने के लिए map लेंगे। अपने आप को validateEmail फंक्शन बनाएं, आप जो भी रेगेक्स चाहते हैं उसका उपयोग करें।

button.rx_tap                                // ControlEvent<Void>
        .withLatestFrom(textField.rx_text)   // Observable<String>
        .map(validateEmail)                  // Observable<Bool>
        .map { (isCorrect) in
            return isCorrect ? "Email is correct" : "Input the correct one, please"
        }                                    // Observable<String>
        .bindTo(label.rx_text)              
        .addDisposableTo(bag) 

किया हुआ! यदि आपको अधिक कस्टम तर्क की आवश्यकता है (जैसे त्रुटि के मामले में त्रुटि के विचार दिखाना, सफलता के लिए एक और स्क्रीन पर संक्रमण करना ...), बस अंतिम Bool स्ट्रीम की सदस्यता लें और वहां लिखें।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow