这里记录一下整个开发的历程.

公司需要进一步提高开发效率, 除了配备的 12 年 13 寸 mac, 其他都还行. 故开始学习 RxSwift 并应用到工程中.

1 抽取出两个基础协议

视图模型协议: 为了约束 Input/Output 模式, 故引入下面的这个协议

swift
/// ViewModel 协议
///
/// 用于约束实际开发中的 ViewModel, 让它们尽量遵循 Input/Output 模式.
///
/// 但并非必须要让所有的 ViewModel 都实现这个协议.
protocol IViewModel {
    associatedtype InputType
    associatedtype OutputType

//    var Input: InputType { set get }
//    var Output: OutputType { get }

    /// 输入输出转换方法
    ///
    /// - Parameter input: ViewModel 的输入类型, ViewController 通过它内部的公共属性(可以是普通的变量或 Subject)提供输入.
    /// - Returns: ViewModel 的输出类型, 内部包含了 ViewModel 可能的输出, ViewController 可以用这些输出来驱动(Drive)视图
    func transform(input: InputType) -> OutputType
}

可绑定视图模型的类型需要实现下面的协议:

swift
/// 可绑定视图模型的类型
///
/// 由于在 iOS 内只有 ViewController 有绑定 ViewModel 的需求, 所以将这个协议设置为 class 可实现.
protocol ViewModelBandable: class {
    associatedtype ViewModelType

    /// 自己对应的 ViewModel
    ///
    /// 由于 ViewModel 并非必须在 View 初始化的时候就存在, 但使用时必须有 ViewModel
    /// 故设置为可选类型(隐式已解包)
    var viewModel: ViewModelType! { set get }

    /// 执行具体的 View 同 ViewModel 间的绑定操作
    func bind()
}

extension ViewModelBandable where Self: UIViewController {
    /// 将指定 ViewModel 设置到 View, 并调用 ViewModelBandable 的 bind() 操作.
    ///
    /// - Parameter viewModel: ViewModel
    func bindViewModel(_ viewModel: Self.ViewModelType) {
        self.viewModel = viewModel
        // 保证在正确的时机后才会进行绑定操作, 否则
        loadViewIfNeeded()
        self.bind()
    }
}

2 利用 RxCocoa 为 TableView 提供数据源

在实际开发中这个需求很常见, 一般来说按照如下套路走即可.

待续.