I do not know RxSwift well enough, and could not figure out my problem on my own. 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. That is, I go to service.uploadPhoto (image: image) twice.
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. The subscriptions only get cleared after the ViewController gets deallocated, which is when the DisposeBag gets destroyed.
Here's what I would do for now: The cell should hold the Observable and the DisposeBag instead. You'll have to clear it in 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:
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. Or you could override TableViewDataSource in a way that your cells can handle their own ViewModels entirely themselves.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.