RxSwift Bir aboneliğin iptal edilmesi, başka bir aboneliğin elden çıkarılmasına neden olur

Aug 18 2020

Bir var PublishSubject<InfoData>bir viewController içinde. Ve ona abone oluyorum, bu yüzden bir olay yaydığında - UIAlertViewController'ı gösteriyorum.

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'da bölüm başlıklarına sahip bir tableView var. Bölüm başlık görünümünde bir infoMessageAction: PublishSubject<InfoData?>. Bir görünüm başlatırken ve viewForHeaderInSectionarasında bir abonelik oluşturuyorum .infoMessageActioninfoData

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
}

Başlık görünümü ilk kez başlatıldığında, her şey iyi çalışır - infoMessageActionbu infoDatada AlertViewController'ın sunumunu tetikleyen tetikler. Başlık görünümünü ekranın ötesine kaydırdığımda , abonelik arasındaki view.infoMessageActionve infoDataimha ettiğim (görünüm tanımlandığı için beklenen davranıştır).

Ama infoDataViewController arasındaki aboneliği de elimden alıyorum . Aldığım event completedve disposeiçin view.infoMessageAction<-> infoDataabonelik ve ayrıca event completedve disposeiçin infoData<-> ViewController aboneliği.

Yalnızca view.infoMessageAction<-> infoDataaboneliğinin kesilmesini bekliyorum. Ayrıca her iki abonelik de farklı disposeBag tarafından düzenlenir. infoData<-> ViewController aboneliği neden elden çıkarılır ve nasıl engellenir?

Şimdiden teşekkürler!

Yanıtlar

DanielT. Aug 18 2020 at 18:28

Sizin başlangıç durumuna FutureSpendingsHeaderViewgetirildiğinde infoMessageAction, kaynağı olan görünüm de başlatılır ve bu görünüm completedo anda bir olay yayar . Tamamlanan bu olay, infoDatadaha sonra kendi tamamlanmış olayını yayınlayacak şekilde aktarılır .

Bir Gözlemlenebilir tamamlanmış bir olay yayınladığında tamamlanmış olur. Daha fazla olay yayamaz. Böylece abonelik elden çıkarılır.

Cevabınız @Alex, görünümünüzdeki şeylerin ilklendirilme sırasını değiştirerek denklemi değiştirir. DisposeBag şimdi ilk olarak sıfırlanıyor, bu da görünüm tamamlanan olayı göndermeden önce gözlemlenebilir zinciri kırıyor.

Daha iyi bir çözüm, a PublishRelayyerine a kullanmak olacaktır PublishSubject. Röleler tamamlanmış olayları yayınlamaz.

Bundan daha da iyisi, konudan tamamen kurtulup şöyle bir şey yapmak olacaktır:

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

Herhangi biri böyle bir durumla karşı karşıya kalırsa, sorunu buldum. Bölüm başlığı görünümünde disposeBagsabit olarak başladım ve görünüm tanımlandığında diğer her şeyin RxSwift tarafından ele alınacağını düşündüm. Bu yüzden görünümü şu şekilde güncelledim:

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

Şimdi abonelik gerektiği gibi elden çıkarılır.