【问题标题】:Disable Realm Sync only for non-premium users仅为非高级用户禁用领域同步
【发布时间】:2025-12-22 06:40:11
【问题描述】:

我正在创建一个 iOS 应用程序,我打算在其中为高级用户提供跨设备功能的数据同步。我发现Realm Sync 是一个很好的解决方案,可以让本地设备上的数据库和云 MongoDB Atlas 保持同步。但是,我不想将非高级用户的数据同步到云数据库。

我正在寻找几种我能想到的方法来防止非高级用户触发 Realm Sync,但我不确定解决这个问题的最佳方法是什么。

  • 利用Sync permissions 防止同步 - 我可以存储高级用户 ID 列表,并且只向这些用户授予同步权限。

     {
       "%%user.id": [
          "5f4863e4d49bd2191ff1e623",
          "5f48640dd49bd2191ff1e624",
          "5f486417d49bd2191ff1e625"
       ]
     } 
    
  • Configure Realm objects 在客户端,即如果用户是高级用户,则只允许所有 Realm 对象/模型。

     // Get a configuration to open the synced realm.
     var configuration = user.configuration(partitionValue: "user=\(user.id)")
     // For non-premium user it would be [User.self]
     configuration.objectTypes = [User.self, Project.self] 
     Realm.asyncOpen(configuration: configuration) { [weak self](result) in /*...*/ }
    

我正在寻找解决此问题的见解/推荐方法。

编辑

我还有一些关于以不同方式处理两个用例的其他问题 - 非高级一个是通过仅打开本地 Realm() 而高级一个使用Realm.asyncOpen()

  1. 当现有用户切换到高级订阅时如何处理用例?是否应该致电Realm.asyncOpen() 就足够了,还是我需要做任何特殊处理?
  2. 我计划为所有用户(高级 + 非高级)同步我的所有 User(集合中的自定义文档)记录。我的猜测是我应该为我的所有内容和同步的 Realm 打开一个普通的 Realm,配置中只有 [User.self] 对象。

【问题讨论】:

    标签: ios mongodb realm mongodb-realm


    【解决方案1】:

    这非常容易做到!

    当您只想使用本地领域时,无需配置即可连接到它 - 像这样

    let realm = try! Realm()
    let someObject = realm.results(SomeObject.self)
    

    或可能包含本地文件名的配置。所有应用数据都只能在本地读写,不会同步。

    当你想使用 MongoDB Realm Sync 时,像这样连接它

    let app = App(id: YOUR_REALM_APP_ID)
    // Log in...
    let user = app.currentUser
    let partitionValue = "some partition value"
    var configuration = user!.configuration(partitionValue: partitionValue)
    Realm.asyncOpen(configuration: configuration) { result in
        switch result {
        case .failure(let error):
            print("Failed to open realm: \(error.localizedDescription)")
            // handle error
        case .success(let realm):
            print("Successfully opened realm: \(realm)")
            // Use realm
        }
    }
    

    然后是配置

    let config = user?.configuration(partitionValue: "some partition")
    let realm = try! Realm(configuration: config)
    

    编辑

    回答两个后续问题:

    当现有用户切换到高级版时如何处理用例 订阅?应该调用 Realm.asyncOpen() 还是我需要 有什么特殊处理吗?

    使用 Sync'ding 解决方案连接到 MongoDB Realm 将添加其他文件并开始同步。如果这是一个“高级”新用户,除了(最初)确保您的对象使用 _id 和 partitionKey 属性正确结构化之外,别无他法。

    如果此用户从仅本地的非高级升级到已同步的高级,您需要将您的领域对象从仅本地领域复制到已同步的领域。

    有几种方法可以做到这一点;可能最简单的做法是在您的应用程序中包含代码,然后在升级时连接到同步领域(使用 .async),然后连接到您现有的本地领域,最后遍历对象以复制到同步领域。

    另一种选择是将领域对象导出为 JSON,然后将它们直接写入服务器。下次您的应用程序与 .async 连接时,它将强制客户端重置并下载并创建本地同步的文件。 Realm Legacy Migration Guide中的一些信息可能有助于此特定过程。

    我计划同步我的所有用户(集合中的自定义文档)记录 适用于所有用户(高级 + 非高级)。我的猜测是我应该打开一个 我所有内容的正常领域和仅与 [User.self] 同步的领域 配置中的对象。

    非高级用户不会同步,因此他们不是真正的“用户”。您不需要存储或同步它们,因此您真的不需要任何身份验证或在服务器上存储任何数据 - 它只是一个本地运行和使用的应用程序,因此甚至不需要担心“用户”对象.一旦他们升级,您将需要这样做。

    【讨论】:

    • 这对我真的很有帮助,因为我刚刚开始使用 Realm。我有几个后续问题,我将添加到问题中。我很想从你那里得到一些见解:)
    • @SiddharthKamaria 很高兴为您提供帮助!尽量将问题限制在一个主题/问题上——当一个问题有多个主题时,答案会很长,很难理解。如果这个答案有帮助,请接受它以便它可以帮助其他人How To Accept,然后为您的其他主题创建一个不同的问题,我们会看看!
    • 我一定会试试这个并告诉你。如果可以,请回答我在答案或 cmets 中提出的两个问题。 :)
    • @SiddharthKamaria 我可以填充分区键并打开一个本地领域!这是正确的。确保在每种情况下都在对象中包含 _id 和分区键,这样如果用户从本地升级到同步,这将是一个平稳的过渡。
    • @SiddharthKamaria ...感谢您指出这一点。我的回答在这一点上有点不清楚,所以我更新了更多信息。