zwvista

导航

ReactiveX 学习笔记(33)使用 RxSwift + RxCocoa + MVVM 进行 GUI 编程

课题

  1. 程序界面由3个文本编辑框和1个文本标签组成。
  2. 要求文本标签实时显示3个文本编辑框所输入的数字之和。
  3. 文本编辑框输入的不是合法数字时,将其值视为0。
  4. 3个文本编辑框的初值分别为1,2,3。

创建工程

打开 Xcode,File / New / Project..
在 New Project 向导的第1页,选 iOS / Single View App
在向导的第2页填上 Product Name: RxExample
在向导的第3页选择任意文件夹点击 Create 按钮创建工程
关闭所创建的工程

配置 Pods

在工程所在文件夹下创建 Podfile 文件,内容如下:

use_frameworks!

target 'RxExample' do
project 'RxExample'
pod 'RxSwift'
pod 'RxCocoa'
pod 'RxBinding'
pod 'NSObject+Rx'
end

打开终端在工程所在文件夹下执行 pod install 命令。

$ cd RxExample
$ pod install
...
Installing NSObject+Rx (5.1.0)
Installing RxBinding (0.4)
Installing RxCocoa (5.1.1)
Installing RxSwift (5.1.1)
...

打开 TwoWayBind.swift 文件,添加 BehaviorRelay<String> 专用的 <~> 操作符函数

public func <~> <T>(relay: BehaviorRelay<String>, textInput: TextInput<T>) -> Disposable {
    return relay.twoWaybind(to: textInput)
}

用 Xcode 打开 RxExample.xcworkspace

配置 UI

打开 Main.storyboard 文件,在 View Controller Scene / View Controller / View 下面放置3个 Text Field 和1个 Label。

控件变量

打开 ViewController.swift 文件,在 ViewController 类中添加控件变量

@IBOutlet weak var tfNumber1: UITextField!
@IBOutlet weak var tfNumber2: UITextField!
@IBOutlet weak var tfNumber3: UITextField!
@IBOutlet weak var lblResult: UILabel!

使用 Assistant Editor 同时打开 Main.storyboard 文件,用 Control 键将控件变量挂到相应的控件上。

使用 MVVM 的解决方案

在 ViewController.swift 文件中添加 RxSwift RxCocoa RxBinding NSObject_Rx 的引用。

import UIKit
import RxSwift
import RxCocoa
@_exported import RxBinding
import NSObject_Rx

在 ViewController.swift 文件中添加 NumbersViewModel 类

class NumbersViewModel: NSObject {
    var number1 = BehaviorRelay(value: "1")
    var number2 = BehaviorRelay(value: "2")
    var number3 = BehaviorRelay(value: "3")
    var result = BehaviorRelay(value: "")
    
    override init() {
        super.init()
        Observable.combineLatest(number1, number2, number3) { num1, num2, num3 -> Int in
            (Int(num1) ?? 0) + (Int(num2) ?? 0) + (Int(num3) ?? 0) }
            .map { String($0) }
            ~> result
            ~ rx.disposeBag
    }
}

在 ViewController 类添加 NumbersViewModel 类的实例,并且在 viewDidLoad 方法中添加绑定控件的代码

class ViewController: UIViewController {
// ...
    var vm: NumbersViewModel!

    override func viewDidLoad() {
        super.viewDidLoad()
        vm = NumbersViewModel()
        vm.number1 <~> tfNumber1.rx.textInput ~ rx.disposeBag
        vm.number2 <~> tfNumber2.rx.textInput ~ rx.disposeBag
        vm.number3 <~> tfNumber3.rx.textInput ~ rx.disposeBag
        vm.result ~> lblResult.rx.text ~ rx.disposeBag
    }
// ...
}

posted on 2020-07-24 00:44  zwvista  阅读(405)  评论(0编辑  收藏  举报