RxSwift + 用户默认值

Posted

技术标签:

【中文标题】RxSwift + 用户默认值【英文标题】:RxSwift + UserDefaults 【发布时间】:2017-03-18 17:22:58 【问题描述】:

我是 RxSwift 的新手,在我的例子中,我想使用 UserDefaults 和 RxSwift 来简化我的代码,所以我在下面的代码中做了这个

我的问题是,当我点击一个单元格时,订阅方法提交了两次?那么我该怎么做才能解决它?非常感谢!

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.
    

【问题讨论】:

【参考方案1】:

这确实是某种错误,我建议使用distinctUntilChanged()

按照@wisper 的建议使用debounce() 可能在大多数情况下都有效,但很危险,因为您依赖于 observable 发出的事件的速度。

【讨论】:

distinctUntilChanged()中只有一个l【参考方案2】:

ios 错误,v10.2

UserDefaults.standard.rx
    .observe(String.self, "key")
+   .debounce(0.1, scheduler: MainScheduler.asyncInstance)
    ...

【讨论】:

【参考方案3】:

您可以尝试使用 take(n),其中 'n' 是可观察序列中连续元素的数量。

tableView.rx
  .itemSelected
  .take(1)
  .subscribe  (indexPath) in
    UserDefaults.standard.set("\(indexPath)", forKey: "key")
  
  .disposed(by: disposeBag)

【讨论】:

【参考方案4】:

如果您只想确保它在您的场景中只发射一次,请按照其他人的建议使用distinctUntilChanged()。请注意,如果您在同一个单元格上点击两次,您的 subscribe 闭包只会发出一次。

如果您想更好地了解它为什么会发出两次,我会检查tableView 上的didSet 是否被调用了两次。你可以试着移动这个块

tableView.rx
  .itemSelected
  .subscribe  (indexPath) in
    UserDefaults.standard.set("\(indexPath)", forKey: "key")

.disposed(by: disposeBag)

viewDidLoad(),看看你有没有同样的问题。

【讨论】:

以上是关于RxSwift + 用户默认值的主要内容,如果未能解决你的问题,请参考以下文章

使用 RxSwift 从 ViewController 向 ViewModel 传递值

根据 UITextField 中的值禁用按钮只能工作一次(RxSwift)

空用户输入的默认值

C#中用户定义类的默认值

Swift 将值添加到现有用户默认值

使用 swift 将数组保存和检索到用户默认值