Swift + Realm:如何从 collection.find 的范围内更改外部变量

Posted

技术标签:

【中文标题】Swift + Realm:如何从 collection.find 的范围内更改外部变量【英文标题】:Swift + Realm: How to change an outer variable from inside a collection.find's scope 【发布时间】:2021-12-08 12:01:09 【问题描述】:

按照this 教程,我编写了以下类:

import RealmSwift
import Darwin
import SwiftUI

let app = App(id: "my-app-id")

class AccessManager: Object 
    @objc dynamic var isInTime: Bool = false
    
    func foo2() -> Bool 
        return true
    

    func foo1() 
        app.login(credentials: Credentials.anonymous)  (result) in
            DispatchQueue.main.async 
                switch result 
                case .failure(let error):
                    print("Login failed: \(error)")
                case .success(let user):
                    print("Login as \(user) succeeded!")
                    
                    let client = app.currentUser!.mongoClient("mongodb-atlas")
                    let database = client.database(named: "my-database")
                    let collection = database.collection(withName: "my-collection")
                    let identity = "my-identity"
    
                    collection.find(filter: ["_partition": AnyBSON(identity)],  (result) in
                        switch result 
                        case .failure(let error):
                            print("Call to MongoDB failed: \(error.localizedDescription)")
                        case .success(let documents):
                            self.bar = self.foo2()
                            print(self.bar) // prints true
                        
                    )
                    print(self.bar) // prints false
                
            
        
    

当我在collection.find 的范围内更改self.bar 的值时(使用self.foo2 函数),它的值不会在该范围之外更改 - 即在第一个print(self.bar) - @987654328 @ 正在打印,但在第二个 - false 被打印。

如何更改self.bar 的值,以便更改也将在collection.find 的范围之外生效?

【问题讨论】:

为了清楚起见,您没有使用 Realm SDK,您正在绕过它并使用 MongoClient 和查询 API 直接与服务器对话。您可能需要考虑 SDK,因为它简化了与后端 MongoDB 服务器的交互。如果您的代码的目标是更新一个值,您可能需要调用collection.updateOneDocument(),它可以在UpdateDocuments 部分中找到。此外,请注意闭包,因为闭包之后的代码将在闭包中的代码之前执行 @Jay 我正在尝试根据 foo2 的结果更新变量 self.bar 的值。但是,我无法以在 collectioniom.find 范围之外生效的方式对其进行更新。 self.bar 不是文档的属性。 对。所以闭包是异步的,闭包之后的代码将(可能)在闭包中的代码之前执行。因此,该代码将在值设置为 true 之前打印 false。代码比互联网快,所以数据只在闭包中有效 @Jay 谢谢!这似乎是问题所在 - 在将 sleep(2) 放在闭包之后的代码之前 - 变量确实更新了。你建议我如何在不使用睡眠的情况下解决这个问题? 如果不了解您要做什么,就很难知道如何回答。设置 self.bar 的目的是什么?序列的下一步是什么?不管它是什么,都应该从闭包中调用它。换一种说法;假设您正在下载要在 tableView 中显示的数据。您调用该函数以从 MongoDB(集合)获取数据,然后在调用之后的闭包中,您将填充您的 dataSource 调用 tableView.reload 以更新 UI。 【参考方案1】:

正如@Jay 评论的那样:

闭包是异步的,闭包之后的代码将 (可能)在闭包中的代码之前执行。所以该代码将打印 在值设置为 true 之前为 false。代码比 互联网,因此数据仅在关闭时有效。

这就是为什么在我的例子中,闭包之外的print(self.bar)collection.find 闭包之前执行。因此它的结果是false 而不是true

【讨论】:

以上是关于Swift + Realm:如何从 collection.find 的范围内更改外部变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中的 Realm.io 中做抽象实体

升级 Swift Realm Braking Changes,我可以更改类名或如何解决冲突?

无法从Swift中的Realm对象Server获取数据

Realm (Swift):如何在迁移期间获取 MutableSet 数据?

Android Realm Schema不匹配错误

将Realm从Swift 4转换为Swift 3