RxSwift एक सदस्यता का निपटान दूसरी सदस्यता का निपटान करता है

Aug 18 2020

मैं PublishSubject<InfoData>एक ViewController में एक है। और मैं इसकी सदस्यता लेता हूं, इसलिए जब यह एक घटना का उत्सर्जन करता है - मैं UIAlertViewController दिखाता हूं।

let infoData = PublishSubject<InfoData>()
private func bindInfoData() {
     infoData.subscribe(onNext: { [weak self] (title, message) in
         self?.presentInfoSheetController(with: title, message: message)
     }).disposed(by: disposeBag)
}

ViewController में मेरे पास अनुभाग हेडर के साथ एक तालिका दृश्य है। अनुभाग हेडर दृश्य में एक है infoMessageAction: PublishSubject<InfoData?>। जब एक दृश्य के शुरू करने के लिए viewForHeaderInSectionमैं के बीच एक सदस्यता बनाने infoMessageActionऔर infoData

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
      let view = FutureSpendingsHeaderView(frame: frame)
      view.infoMessageAction
            .compactMap { $0 }
            .bind(to: infoData)
            .disposed(by: view.disposeBag)
      return view
}

हैडर दृश्य पहली बार के लिए शुरू की जब सब काम करता है अच्छा - infoMessageActionचलाता infoDataहै जो बदले में AlertViewController की चलाता प्रस्तुति। जब मैं हेडर स्क्रीन को स्क्रीन के परे सब्स्क्राइब करता हूं view.infoMessageActionऔर infoDataडिसपोज़ करता है (जिसे देखने की उम्मीद की गई थी कि यह अपेक्षित व्यवहार है)।

लेकिन मैं infoDataऔर ViewController के बीच सदस्यता का निस्तारण करवाता हूं । मैं प्राप्त event completedऔर disposeके लिए view.infoMessageAction<-> infoDataसदस्यता और भी event completedऔर disposeके लिए infoData<-> ViewController सदस्यता।

मुझे उम्मीद है कि केवल view.infoMessageAction<-> infoDataसदस्यता टूटनी चाहिए। इसके अलावा दोनों सदस्यता अलग निपटान द्वारा निपटाया। क्यों infoData<-> ViewController सदस्यता निपटाया और इसे रोकने के लिए कैसे?

अग्रिम में धन्यवाद!

जवाब

DanielT. Aug 18 2020 at 18:28

जब आपका FutureSpendingsHeaderViewविघटन किया जाता है, तो जो भी स्रोत है, infoMessageActionवह भी विखंडित किया जा रहा है, और यह दृश्य completedउस समय की घटना का उत्सर्जन करता है । उस पूर्ण घटना को पारित कर दिया जाता है, infoDataजिसके बाद वह अपने स्वयं के पूर्ण कार्यक्रम का उत्सर्जन करता है।

एक बार जब एक ऑब्जर्वेबल ने एक पूर्ण घटना का उत्सर्जन किया है, तो यह किया जाता है। यह किसी भी अधिक घटनाओं का उत्सर्जन नहीं कर सकता। तो इसके लिए सदस्यता का निपटान किया जाता है।

आपके उत्तर @ एलेक्स ने ऑर्डर को बदलकर समीकरण को बदल दिया है कि आपके दृश्य के अंदर चीजें डीनीट्यूलाइज्ड हो जाती हैं। डिस्पोज़बाग को पहले अब विखंडित किया जा रहा है, जो देखने से पहले पूरी की गई श्रृंखला को तोड़ देता है।

एक बेहतर समाधान के PublishRelayबजाय एक का उपयोग करना होगा PublishSubject। रिले पूर्ण घटनाओं का उत्सर्जन नहीं करते हैं।

इससे भी बेहतर यह होगा कि विषय से पूरी तरह छुटकारा पाएं और कुछ ऐसा करें:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let view = FutureSpendingsHeaderView(frame: frame)
    view.infoMessageAction
        .compactMap { $0 }
        .subscribe(onNext: { [weak self] (title, message) in
            self?.presentInfoSheetController(with: title, message: message)
        })
        .disposed(by: view.disposeBag)
    return view
}
Alex Aug 18 2020 at 16:20

समस्या मिली, अगर किसी को ऐसी स्थिति का सामना करना पड़ता है। सेक्शन हेडर व्यू में मैंने disposeBagनिरंतर के रूप में पहल की और सोचा कि जब दृश्य समाप्त हो जाए तो बाकी सब कुछ खुद RxSwift ने संभाला। इसलिए मैंने यह देखने के लिए अद्यतन किया:

var disposeBag = DisposeBag()
    
deinit {
    disposeBag = DisposeBag()
}

अब सदस्यता को आवश्यकतानुसार निपटाया जाता है।