我有一个视图控制器,可以为用户打开模式视图控制器以从其库中选择图像。为此,我使用了我编写的DKImagePickerController
的Rx包装器。
视图控制器中的相关代码如下:
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
的绑定以进行处置?如何避免资源泄漏? 最佳答案
我怀疑是因为completed
通过第二条链(MediaViewModel.bind
中的那一条)传播了,所以它将不再接收任何事件。我认为您想在此处使用subscribe(onNext: { ... })
而不是bind
,以便避免发送错误和完成事件。
另一种选择是使用PublishRelay
而不是PublishSubject
。
PublishRelay是PublishSubject
的包装。与PublishSubject
不同,它不能以错误或完成而终止。