首页 文章

境界列表KVO观察

提问于
浏览
1

Realm Swift文档指出,您可以使用KVO观察模型类上使用的大多数属性 . 使用ReactiveCocoa,对于我在模型类上的每个属性,我创建了一个类似的 rac_ 前缀属性,它发送值更改,然后我可以使用它来绑定到MVVM样式体系结构中的视图 .

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

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)它从外部不可变( AnyProperty vs MutableProperty 和2)只有模型与 .takeUntil(self.willDeallocSignal()) 一起生存 . (我也想问一下,这里需要_1317161位吗?我不确定 self 是否被捕获,总是那么糟糕) .

问题出在 List 属性中 . 列表可以在objective-c中表示 . 关键 Value 观察工作得很好,有一个主要的警告 .

使用关系列表属性获取相同的类:

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

相应的反应性观察属性应该看起来像是:

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 个对象 . 我不得不jerryrig一个看起来像这样的信号发生器:

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 s或b)一种在列表属性上发出kvo的方法 . 我使用传统的KVO进行了测试并获得了相同的结果 .

2 回答

  • 0

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

    此方法采用闭包,在 every 更改时调用 . 至少只要您不阻止运行循环,通知就可能会合并 . 通过此机制也会报告初始值,因此您可能会获得其他信号,这可能是您不期望的 .

    您应该可以使用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后,您还将获得细粒度通知,这将通知您列表中的详细更改 .

  • 1
    func observeAppVarProperties(properties: [String]) -> Observable<AppVarsObject> {
            return Observable.create { observer in
                guard let globals = try! Realm().objects(AppVarsObject.self).first else {
                    observer.onError(NSError(domain: "", code: 0, userInfo: nil))
                    return Disposables.create()
                }
                observer.onNext(globals)
                let notificationToken = globals.observe { (changed) in
                    switch changed {
                    case .change(let propertyChanges):
                        if propertyChanges.filter({ properties.contains($0.name) }).count > 0 {
                            observer.onNext(globals)
                        }
                    case .deleted:
                        observer.onNext(globals)
                    case .error(let error):
                        observer.onError(error)
                    }
                }
                return Disposables.create {
                    notificationToken.invalidate()
                }
            }
        }
    

相关问题