如何将标准模型 class/struct 变成可观察的属性?

How to turn a standard model class/struct into observable properties?

我正在将 ReactiveKit 与他们的 Bond 扩展一起使用,但我真的不知道如何做一些感觉很基本的事情。

假设我的应用程序中有一个用户模型。像这样。

class User: Codable {
  var id: String
  var firstName: String?
  var avatar: String?
}

内容来自远程 API,通过向 Codable 确认一切正常且简单。

但我们也可以举个例子,我想要从模型 属性 到某个 UI 状态的双向绑定;这是不可能的,因为我的属性 none 与 BindableProtocol 一致。或者,如果我想观察模型属性的变化,这当然也是不可能的。

所以我的问题是:如何在不破坏现有用户模型和行为的情况下将我的模型属性转换为实际可观察​​属性?例如,它仍然需要是可编码的。我是否要创建第二个 ObservableUser class,然后在 User 模型的所有属性中设置 didSet 以将更改写入 ObservableUser?在 ObservableUser 上做一些类似的事情来将更改写回 User?这看起来很可怕,希望不是重新开始的前进方式。

您不需要创建另一个对象来使模型属性可观察。但是实施 decoder & encoder 方法和编码键 enum 肯定会有开销,这在许多情况下也是标准做法,

class User: Codable {
    var id: String = ""
    var firstName = Observable<String?>(nil)
    var avatar = Observable<String?>(nil)

    private enum CodingKeys: String, CodingKey {
        case id, firstName, avatar
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.id = try container.decode(String.self, forKey: .id)
        self.firstName.value = try container.decode(String.self, forKey: .firstName)
        self.avatar.value = try container.decode(String.self, forKey: .avatar)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(self.id, forKey: .id)
        try container.encode(self.firstName.value, forKey: .firstName)
        try container.encode(self.avatar.value, forKey: .avatar)
    }
}

现在您可以绑定任何 UIView 元素。


通常,使用反应式方法,ViewModel 是您创建 bindable 属性的地方,这些属性为您的模型提供价值以查看和更新​​模型 属性 通过保持模型在视图中不可见.