【问题标题】:Reading Data from Realm Database (Swift)从领域数据库中读取数据 (Swift)
【发布时间】:2019-12-25 18:46:41
【问题描述】:

我是 Realm DataBase 的新手,我需要一种从 realmCloud 读取数据的方法,但来自两个不同的应用程序项目。我尝试实现这一点的方法是使用查询同步领域。目前我正在使用单个领域用户在一个应用程序中写入数据,并使用同一个领域用户从另一个应用程序读取数据。问题是从第二个应用程序(用于读取的应用程序)进行查询不会返回任何领域对象(我还注意到用户标识符与第一个不同,并且用户权限为零。

我已尝试直接从 RealmStudio 设置权限,因为文档没有准确说明如何从代码中设置权限

func openRealm() {
    do {
        realm = try Realm(configuration: SyncUser.current!.configuration())
        let queryResults = realm.objects(*className*.self)
        let syncSubscription = queryResults.subscribe()
        let notificationToken = queryResults.observe() { [weak self] (changes) in
            switch (changes) {
            case .initial: print(queryResults)
            case .error(let error): print(error)
            default: print("default")
            }
        }
        for token in queryResults {
            print(token.tokenString)
        }
        syncSubscription.unsubscribe()
        notificationToken.invalidate()
    } catch {
        print(error)
    }
}

此函数打印一个应用项目中的数据,但在另一个应用项目中使用相同的用户登录,并且项目中引用了相同的classFile,它没有。 (注意SyncUser.current.identifier 也不同

【问题讨论】:

    标签: swift database synchronization realm


    【解决方案1】:

    有几个问题。

    其中一些调用是异步的,您问题中的代码在数据同步(检索)之前超出范围。底线是代码比互联网快,您需要围绕异步调用设计应用程序流程;在数据可用之前不要尝试使用它。

    例如

        let notificationToken = queryResults.observe() { [weak self] (changes) in
           //here is where results are fully populated
        }
    
        // this code may run before results are populated //
        for token in queryResults {
            print(token.tokenString)
        }
    

    另外,let notificationToken 是一个本地变量,并且在结果被填充之前就超出了范围。

    这些问题非常容易解决。首先是在等待填充结果时保持通知令牌处于活动状态,其次是在闭包内处理结果,因为那是它们有效的时候。

    var notificationToken: NotificationToken? = nil //a class var
    
    func openRealm() {
        do {
            let config = SyncUser.current?.configuration()
            let realm = try Realm(configuration: config!)
            let queryResults = realm.objects(Project.self)
            let syncSubscription = queryResults.subscribe(named: "my-projects")
            self.notificationToken = queryResults.observe() { changes in
                switch changes {
                case .initial:
                    print("notification: initial results are populated")
                    queryResults.forEach { print($0) }
                case .update(_, let deletions, let insertions, let modifications):
                    print("notification: results, inserted, deleteed or modified")
                    insertions.forEach { print($0) } //or mods or dels
                case .error(let error):
                    fatalError("\(error)")
                }
            }
        } catch {
            print(error)
        }
    }
    
    deinit {
       self.notificationToken?.invalidate()
    }
    

    保持该令牌(及其相应代码)有效的另一个好处是,当有进一步的更改时,您的应用会收到通知。因此,例如,如果添加了另一个项目,“更改”部分中的代码将运行并显示该更改。

    【讨论】:

    • 你好杰!非常感谢。您提到的所有内容都是正确的,但我还想为遇到相同问题的每个人添加一个事实,即当我调用 SyncUser.logIn(*login parameters') 时,以前登录的用户以某种方式仍然被缓存,并且这也会产生不一致的查询结果。我应用的修复以及您的建议是:对于 SyncUser.all { user.value.logOut() } 中的用户,然后调用 SyncUser.logIn
    • @OctavianMilea 是的——当然,Realm 会记住上次登录的用户,但是,除非查询与特定用户相关联,否则它不应该创建不一致的查询结果。例如,查询realm.objects(Project.self).filter("owner = %@", SyncUser.current!.identity!) 将返回创建该对象的用户的结果,只要保存时填充了所有者属性。如果您将其更改为我的问题中所示的查询,它将返回所有项目,而不管用户如何。如果它不适合您,请发布另一个问题,我们会看看。
    • 这很奇怪,因为当我第一次构建应用程序时,即使领域路径和用户凭据相同,用户身份属性与其他项目不同,只有在我注销所有用户并再次登录,用户身份与其他应用中的用户身份相同
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多