【问题标题】:RxSwift - Two-way binding to use the same screen to edit and add modelRxSwift - 双向绑定使用同一屏幕编辑和添加模型
【发布时间】:2018-05-13 20:55:39
【问题描述】:

我可以将UITextField.rx.text 绑定到Variable<T>。当我进入“创建”屏幕时,这很好用。但是,假设我已经创建了一个模型并想在同一个屏幕上对其进行编辑,我该怎么做呢?

我还看到了很多关于以<-> 运算符为代表的中缀运算符。如果我没有配置这个中缀运算符,我总是需要做大量的工作来实现双向绑定?

这是我的代码

struct TodoViewModel: CustomDebugStringConvertible {
    let title = Variable<String?>("Initial title")
    let description = Variable<String?>("")
    let dueDate = Variable<Date?>(Date())
    let done = Variable<Bool>(false)

    var debugDescription: String {
        get {
            return
                """
                // ======
                Title: \(self.title.value ?? "Nil")
                Description: \(self.description.value ?? "Nil")
                Due Date: \(String(describing: self.dueDate.value))
                Done: \(self.done.value)
                """
        }
    }
}

// ViewController
class AddTaskTableViewController: UITableViewController {
    @IBOutlet weak var labelTitle: UILabel!
    @IBOutlet weak var txtTitle: UITextField!
    @IBOutlet weak var txtDescription: UITextField!
    @IBOutlet weak var txtDate: UITextField!
    @IBOutlet weak var switchDone: UISwitch!

    var todo = TodoViewModel()
    var disposeBag = DisposeBag()
    let dateFormatter = DateFormatter()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.dateFormatter.locale = Locale(identifier: "en-US")

        // Configuring reactivity
        // Binds the UITextField's text value to my Model
        // let _ = self.txtTitle.rx.text.bind(to: self.todo.title).disposed(by: self.disposeBag)

        // ⬆⬇ Makes more sense they both being a two-way binding. This way I can edit and add items using the same screen.

        // Binds my model's title to the UITextView's text
        // let _ = self.todo.title.asObservable().bind(to: self.txtTitle.rx.text)
        let _ = self.txtDate.rx.text.map{ strDate in
            return self.dateFormatter.date(from: strDate!)
        }.bind(to: self.todo.dueDate).disposed(by: self.disposeBag)
        let _ = self.txtDescription.rx.text.bind(to: self.todo.description).disposed(by: self.disposeBag)
        let _ = self.switchDone.rx.isOn.bind(to: self.todo.done).disposed(by: self.disposeBag)

        let _ = self.todo.title.asObservable().bind(to: self.labelTitle.rx.text).disposed(by: self.disposeBag)
    }
}

【问题讨论】:

    标签: ios swift rx-swift reactivex rx-cocoa


    【解决方案1】:

    我很想拥有两个初始化器:一个用于创建新的待办事项,另一个用于编辑现有的:

    let title: Variable<String?>
    let description: Variable<String?>
    let dueDate: Variable<Date?>
    let done: Variable<Bool>
    
    init() {
        self.title = Variable<String?>("Initial title")
        self.description = Variable<String?>("")
        self.dueDate = Variable<Date?>(Date())
        self.done = Variable<Bool>(false)
    }
    
    init(todo: TodoModel) {
        self.title = Variable<String?>(todo.title)
        self.description = Variable<String?>(todo.description)
        self.dueDate = Variable<Date?>(todo.dueDate)
        self.done = Variable<Bool>(todo.done)
    }
    

    如您所见,中缀&lt;-&gt; 运算符将变量绑定到控件属性并订阅控件属性的更改以更新变量。它还捆绑了它们的一次性物品,因此它们具有相同的生命周期,并确保在控件属性的订阅完成时所有东西都被处理掉。这是来源:

    func <-> <T>(property: ControlProperty<T>, variable: Variable<T>) -> Disposable {
        let bindToUIDisposable = variable.asObservable()
            .bindTo(property)
        let bindToVariable = property
            .subscribe(onNext: { n in
                variable.value = n
            }, onCompleted:  {
                bindToUIDisposable.dispose()
            })
    
        return StableCompositeDisposable.create(bindToUIDisposable, bindToVariable)
    }
    

    如果您想避免使用 &lt;-&gt; 运算符,那么您需要自己为每个双向绑定执行所有这些操作。

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-30
      • 2012-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多