ios - Realm 列表 KVO 观察

标签 ios swift mvvm realm reactive-cocoa

Realm Swift 文档指出,您在模型类上使用的大多数属性都可以使用 KVO 来观察。使用 ReactiveCocoa,对于模型类上的每个属性,我创建一个类似的 rac_ 前缀属性,该属性发送值更改,然后我可以使用它绑定(bind)到 MVVM 风格架构中的 View 。

示例模型类可能如下所示:

 class Post: Object {
     dynamic var text = ""
     private(set) lazy var rac_text: AnyProperty<String> = { [unowned self] in
         return AnyProperty(initialValue: self.name, signal: self.rac_valuesForKeyPath("text", observer: self).toSignal().takeUntil(self.willDeallocSignal())
     }()
 }

这非常方便,因为 1)它不能从外部改变(AnyPropertyMutableProperty 和 2)只要模型与 一起存在,它就存在。 takeUntil(self.willDeallocSignal())。 (我还想问,这里有必要使用[unowned self]位吗?我不确定self是否被捕获,总是不擅长)。

问题出在 List 属性上。列表不能被标记为动态,这是有道理的,它们的类型不能在 Objective-C 中表示。键值观察效果很好,但有一个主要警告。

采用具有关系列表属性的同一类:

class Post: Object {
    let users: List<User> = List<User>()
}

相应的 react 性观察属性应该类似于:

private(set) lazy var rac_users: AnyProperty<List<User>> = {
    return AnyProperty(initialValue: self.users, signal: self.rac_valuesForKeyPath("users", observer: self).toSignal().takeUntil(self.willDeallocSignal()))
}()

但是根据观察,信号不会发出 List 对象,而是发出 RLMArray 对象。我不得不临时搭建一个信号生成器,如下所示:

private(set) lazy var rac_posts: AnyProperty<List<Post>> = { [unowned self] in
    return AnyProperty<List<Post>>(initialValue: self.posts, producer: self.rac_valuesForKeyPath("posts", observer: self)
        .toSignalProducer()
        .assumeNoErrors()
        .map { $0 as! RLMArray }
        .map { array in
            var list = List<Post>()
            for i in 0..<array.count {
                if let element =  array[i] as? Post {
                    list.append(element)
                }
            }
            return list
    })
}()

当然,if let 语句总是失败,因为 RLMObject 无法转换为 Post。因此,我要么需要 a) 一种将 RLMObject 转换为 Object 的方法,要么 b) 一种在发出列表的列表属性上进行 kvo 的方法。我使用传统的 KVO 进行了测试,得到了相同的结果。

最佳答案

您可以使用 Realm Swift 观察 List 类型的属性 addNotificationBlock .

此方法采用一个闭包,每次更改时都会调用该闭包。至少只要您不阻塞运行循环,通知就可能会合并。初始值也是通过此机制报告的,因此您可能会通过该机制获得您可能意想不到的其他信号。

您应该能够将其与 Reactive Cocoa 连接起来,如下所示:

private(set) lazy var rac_posts: AnyProperty<List<Post>> = { [unowned self] in
    return AnyProperty<List<Post>>(initialValue: self.posts, signal: Signal<List<Post>>() { [unowned self] observer in
        let notificationToken = self.posts.addNotificationBlock { list in
            observer.sendNext(list)
        }

        return ActionDisposable() {
            notificationToken.stop()
        }
    }
}()

一次#3359合并后,您还将收到细粒度的通知,通知您列表中的详细更改。

关于ios - Realm 列表 KVO 观察,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36638546/

相关文章:

ios - 如何在 Swift 中将本地时间日期转换为 UTC?

swift - 防止同时执行任务

ios - Metal iOS 给出编译错误

Silverlight MVVM 链接模型和 View 模型

c# - 我在实现异步 RelayCommand 时犯了什么错误?

ios - XCode 无法编辑核心数据模型

ios - UICollectionViewCell 以固有大小展开/折叠

ios - 在 objective-c 中使用异步代码避免嵌套 block

ios - Swift 中的通用异或交换

c# - 使用 MVVM 模式时,我应该将与 View 紧密连接但体积庞大的方法放在哪里?