0

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

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

这是我的代码

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)
    }
}
4

1 回答 1

0

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

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)
}

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

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)
}

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

希望有帮助。

于 2018-02-14T16:20:09.317 回答