I am new here about RxSwift, In my case, I want to use UserDefaults with RxSwift to simplify my code, so I did this following code
my question is, when I clicked a cell, but the subscribe method submit twice? so what should I do to fix it? thx a lot!
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class ViewController: UIViewController {
    let disposeBag = DisposeBag()
    @IBOutlet weak var tableView: UITableView! {
        didSet {
            tableView.register(UITableViewCell.self, forCellReuseIdentifier: String(describing: UITableViewCell.self))
            tableView.rx
                .itemSelected
                .subscribe { (indexPath) in
                    UserDefaults.standard.set("\(indexPath)", forKey: "key")
                }
                .disposed(by: disposeBag)
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        UserDefaults.standard.rx
            .observe(String.self, "key")
            // .debug()
            .subscribe(onNext: { (value) in
                if let value = value {
                    print(value)
                }
            })
            .disposed(by: disposeBag)
        let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, String>>()
        dataSource.configureCell = { (dataSource, tableView, indexPath, item) in
            let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UITableViewCell.self), for: indexPath)
            cell.textLabel?.text = item
            return cell
        }
        Observable.just([SectionModel(model: "", items: (0..<5).map({ "\($0)" }))])
            .bindTo(tableView.rx.items(dataSource: dataSource))
            .disposed(by: disposeBag)
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
                At runtime, you use UserDefaults objects to read the defaults that your app uses from a user's defaults database. UserDefaults caches the information to avoid having to open the user's defaults database each time you need a default value.
The UserDefaults class looks up the value for the key that is passed to the object(forKey:) method and returns a value if a value exists for the given key. It returns nil if no value exists for the given key. The UserDefaults class also defines a number of convenience methods for retrieving values of a specific type.
The beauty of this aspect of UserDefaults is that it still offers us a 100% synchronous API, even though changes are propagated to multiple apps or extensions asynchronously in the background.
It's indeed some kind of a bug and I would recommed to use distinctUntilChanged().
Using debounce() as suggested by @wisper might work most of the time but is dangerous because you are relying on speed of events emitted by observable.
iOS bug, v10.2
UserDefaults.standard.rx
    .observe(String.self, "key")
+   .debounce(0.1, scheduler: MainScheduler.asyncInstance)
    ...
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With