【问题标题】:RxSwift PublishSubject getting unintentionally disposedRxSwift PublishSubject 无意中被丢弃
【发布时间】:2017-11-20 08:56:08
【问题描述】:

我有一个视图控制器,它打开一个模态视图控制器,供用户从其库中选择图像。为此,我使用了我编写的 DKImagePickerController 的 Rx 包装器。

ViewController中的相关代码如下:

fileprivate func addPicturesFromLibrary() {
    guard let viewModel = self.viewModel else { return }

    let pickerController = DKImagePickerController()
    pickerController.singleSelect = false
    pickerController.maxSelectableCount = 10
    pickerController.showsCancelButton = true
    pickerController.sourceType = .photo

    pickerController.rx.didSelectAssets()
        .debug("???? 1")
        .bind(to: viewModel.addAssetsInput)
        .disposed(by: disposeBag)

    self.present(pickerController, animated: true, completion: nil)
}

我的视图模型如下所示:

class MediaViewModel {

      var selectedImages = Variable<[MediaListingImage]>([])

      public let addAssetsInput = PublishSubject<DKAsset>()

      init() {
         bind()
      }

      private func bind() {
          addAssetsInput
              .debug("???? 2")
              .flatMap {
                  $0.rx.fetchOriginalImage()
              }
              .map {
                  MediaListingImage.local($0)
              }
              .subscribe(onNext: { [weak self] (mediaListingImage) in
                  self?.selectedImages.value.append(mediaListingImage)
              })
              .disposed(by: disposeBag)
      }
}

当我打开第一个模式选择器时,它按预期工作。但是,当它释放时,视图模型中的绑定也会释放,因此模态视图控制器的后续呈现将不起作用。

这是我在控制台中获得的日志,它可能有助于您理解我看到的内容:

2017-11-15 17:33:15.490: ???? 2 -> subscribed
2017-11-15 17:33:21.452: ???? 1 -> subscribed
2017-11-15 17:33:23.902: ???? 1 -> Event next(<DKImagePickerController.DKAsset: 0x6080002ab940>)
2017-11-15 17:33:23.902: ???? 2 -> Event next(<DKImagePickerController.DKAsset: 0x6080002ab940>)
2017-11-15 17:33:23.902: ???? 1 -> Event completed
2017-11-15 17:33:23.903: ???? 2 -> Event completed
2017-11-15 17:33:23.903: ???? 2 -> isDisposed
2017-11-15 17:33:23.903: ???? 1 -> isDisposed
2017-11-15 17:33:29.924: ???? 1 -> subscribed
2017-11-15 17:33:33.114: ???? 1 -> Event next(<DKImagePickerController.DKAsset: 0x60c0002a62a0>)
2017-11-15 17:33:33.114: ???? 1 -> Event completed
2017-11-15 17:33:33.114: ???? 1 -> isDisposed

如果我将视图控制器中的代码更改为:

    pickerController.rx.didSelectAssets()
        .debug("???? 1")
        .subscribe(onNext: { (asset) in
            viewModel.addAssetsInput.onNext(asset)
        })
        .disposed(by: disposeBag)

它按预期工作。但是,我发现在这种情况下使用 bind 更优雅,如果可能的话,我想继续使用它。

是什么触发了视图模型中PublishSubject 的绑定来处理?如何在不泄漏资源的情况下防止它?

【问题讨论】:

  • disposeBag是第一个sn-p中ViewController的属性,第二个sn-p中disposeBag是ViewModel的属性吗?
  • @shpasta 是的,两者都是各自类的属性。

标签: ios rx-swift


【解决方案1】:

我怀疑因为completed 通过第二个链(MediaViewModel.bind 中的那个)传播,它将不再接收任何事件。我认为您应该在这里使用subscribe(onNext: { ... }) 而不是bind,这样您就可以避免发送错误和完成事件。

另一种选择是使用PublishRelay 而不是PublishSubject

PublishRelay 是PublishSubject 的包装器。与PublishSubject 不同,它不能以错误或已完成而终止。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    • 1970-01-01
    • 2015-05-23
    • 2016-05-13
    • 1970-01-01
    相关资源
    最近更新 更多