简体   繁体   English

RxSwift。 订阅发生两次

[英]RxSwift. Subscription occurs twice

I do not know RxSwift well enough, and could not figure out my problem on my own.我不太了解 RxSwift,也无法自己解决我的问题。 I would be very grateful for the help.我将非常感谢您的帮助。 Sorry for my English.对不起我的英语不好。

//declare variables    

var loadedImage = BehaviorRelay<UIImage?>(value: nil)

//Subscribe when creating a cell

loadedImage
            .do(onNext: { (_) in
                cell.activityIndicator.startAnimating()
                cell.activityIndicator.isHidden = false
            })
            .flatMap { (image) -> Observable<String> in
                guard let image = image else { return Observable.just("") }
                return service.uploadPhoto(image: image)
            }
            .observeOn(MainScheduler.instance)
            .subscribeNext { (imageName) in
                vc.createEventData.imageName = imageName

                cell.activityIndicator.stopAnimating()
                cell.activityIndicator.isHidden = true

                let currentPhoto = self.object?.placeholderPhoto
                let image = self.loadedImage.value

                cell.photoEventImageView.image = image == nil ? currentPhoto : image

                if let photoPath = self.object?.photoPath, image == nil {
                    if photoPath != "uploads/photos/.png" {
                        let url = URL(string: "http://test-around.profsoft.online/" + photoPath)
                        cell.photoEventImageView.kf.setImage(with: url)

                        if let r = photoPath.range(of: "/", options: .backwards) {
                            let imageName = photoPath.substring(from: r.upperBound)
                            vc.createEventData.imageName = imageName
                        }
                    }
                }

            }
            .disposed(by: disposeBag)

//I throw a signal when choosing a photo

   func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        guard let image = info[.originalImage] as? UIImage else { return }
        loadedImage.accept(image)
        self.viewController?.dismiss(animated: true, completion: nil)
    }

I can't understand why the subscription occurs 2 times.我不明白为什么订阅会发生 2 次。 That is, I go to service.uploadPhoto (image: image) twice.也就是我go到service.uploadPhoto(image:image)两次。

I can only speculate here based on the code you posted but you probably don't unsubscribe when the cell gets reused.我只能根据您发布的代码在这里推测,但当单元格被重用时您可能不会取消订阅。 Therefore and since the disposeBag is held by the ViewController when cellForRowAtIndexPath gets called you will just add another subscription.因此,由于 disposeBag 在调用cellForRowAtIndexPath时由 ViewController 持有,因此您只需添加另一个订阅。 The subscriptions only get cleared after the ViewController gets deallocated, which is when the DisposeBag gets destroyed.只有在 ViewController 被释放后,订阅才会被清除,也就是 DisposeBag 被销毁的时候。

Here's what I would do for now: The cell should hold the Observable and the DisposeBag instead.这是我现在要做的:单元格应该包含 Observable 和 DisposeBag 。 You'll have to clear it in prepareForReuse :您必须在prepareForReuse中清除它:

class YourCell: UITableViewCell {
   var disposeBag = DisposeBag()
   var yourObservable: Observable<UIImage?>?

   func configure(with yourObservable: Observable<UIImage?>) {
      yourObservable = yourObservable
         .subscribe(onNext: /*your code*/ }
         .disposed(by: disposeBag)
   }

   override func prepareForReuse() {
      super.prepareForReuse()
      disposeBag = DisposeBag()
   }
}

and then in your ViewController:然后在你的 ViewController 中:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   let observable = loadedImage /* additional config if needed */
   let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR IDENTIFIER HERE", for: indexPath) as! YourCell
   cell.configure(with: observable)
   return cell
}

At this point you might also want to think about your architecture.此时,您可能还想考虑您的架构。 For example your could manage the observable supplying the data for the cells so that you can just bind it to the tableview and let rx manage everything.例如,您可以管理为单元格提供数据的可观察对象,以便您可以将其绑定到 tableview 并让 rx 管理所有内容。 Or you could override TableViewDataSource in a way that your cells can handle their own ViewModels entirely themselves.或者,您可以覆盖 TableViewDataSource,使您的单元格可以完全自己处理自己的 ViewModel。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM