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 ฉันมี tableView ที่มีส่วนหัวของส่วน มุมมองส่วนหัวมีไฟล์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ควรหยุดทำงาน นอกจากนี้การสมัครสมาชิกทั้งสองถูกกำจัดโดย disposeBag ที่แตกต่างกัน ทำไมinfoData<-> การสมัครสมาชิก ViewController จึงถูกกำจัดและจะป้องกันได้อย่างไร?

ขอบคุณล่วงหน้า!

คำตอบ

DanielT. Aug 18 2020 at 18:28

เมื่อคุณFutureSpendingsHeaderViewถูกยกเลิกการกำหนดค่าเริ่มต้นมุมมองใดก็ตามที่เป็นแหล่งที่มาของinfoMessageActionจะถูกยกเลิกการกำหนดค่าเริ่มต้นด้วยและมุมมองนั้นจะทำให้completedเกิดเหตุการณ์ในเวลานั้น เหตุการณ์ที่เสร็จสมบูรณ์นั้นจะถูกส่งต่อไปinfoDataซึ่งจะแสดงเหตุการณ์ที่เสร็จสมบูรณ์ของตัวเอง

เมื่อ Observable ปล่อยเหตุการณ์ที่เสร็จสมบูรณ์แล้วก็เสร็จสิ้น มันไม่สามารถปล่อยเหตุการณ์ได้อีกแล้ว ดังนั้นการสมัครสมาชิกจึงถูกกำจัด

คำตอบของคุณ @Alex เปลี่ยนสมการโดยการเปลี่ยนลำดับที่สิ่งต่างๆในมุมมองของคุณจะถูกยกเลิก disposeBag กำลังถูก deinitialized ก่อนซึ่งจะทำลายห่วงโซ่ที่สังเกตได้ก่อนที่มุมมองจะส่งเหตุการณ์ที่เสร็จสมบูรณ์

ทางออกที่ดีกว่าคือการใช้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()
}

ตอนนี้การสมัครสมาชิกจะถูกกำจัดตามความจำเป็น