在应用生命周期的中间将本地 Realm 转换为同步的 Realm(在 Swift 中)



我的应用将具有一项名为"多设备同步"的付费功能。我想通过 Realm Cloud - 基于查询的同步来实现该功能。

我知道如何将本地领域转换为同步领域,这要归功于 这个线程。

但这是基于用户从应用程序开始同步他们的 Realm 数据库的场景 - 在打开他们未同步的本地领域之前。这对我不起作用,因为我的用户在付费时会开始同步。

因此,我必须在应用程序生命周期的中间转换他们的本地领域,而本地领域已经在那时打开了。

我的问题来了。当我尝试将本地领域转换为同步领域时,应用程序崩溃并显示以下消息:

路径上的境界"..."已以不同的读取权限打开。

我试图在转换之前找到一种方法来关闭本地 Realm,但是 Realm cocoa 不允许我以编程方式关闭 Realm。

这是我的代码,将本地 Realm 转换为同步的 Realm。

func copyLocalRealmToSyncedRealm(user: RLMSyncUser) {
let localConfig = RLMRealmConfiguration()
localConfig.fileURL = Realm.Configuration.defaultConfiguration.fileURL
localConfig.dynamic = true
localConfig.readOnly = true
// crashes here
let localRealm = try! RLMRealm(configuration: localConfig)
let syncConfig = RLMRealmConfiguration()
syncConfig.syncConfiguration = RLMSyncConfiguration(user: user,
realmURL: realmURL,
isPartial: true,
urlPrefix: nil,
stopPolicy: .liveIndefinitely,
enableSSLValidation: true,
certificatePath: nil)
syncConfig.customSchema = localRealm.schema
let syncRealm = try! RLMRealm(configuration: syncConfig)
syncRealm.schema = syncConfig.customSchema!
try! syncRealm.transaction {
let objectSchema = syncConfig.customSchema!.objectSchema
for schema in objectSchema {
let allObjects = localRealm.allObjects(schema.className)
for i in 0..<allObjects.count {
let object = allObjects[i]
RLMCreateObjectInRealmWithValue(syncRealm, schema.className, object, true)
}
}
}
}

任何帮助将不胜感激。 谢谢。

我制作了本地领域文件的副本,并使用 RLMRealmConfiguration 打开了副本。之后,只需删除两个文件即可。这不是最好的解决方案,但它有效

我认为最好的方法是拥有 2 个领域。就我而言,我使用的是SwiftUI。如果用户已登录,我将使用不同的配置。

struct ContentView: View {

@ObservedObject var app = Realm.app

var body: some View {
if let config = app.createFlexibleConfiguration() {
MainScreenSync()
.environment(.realmConfiguration, config)
.environmentObject(app)
} else {
MainScreen()
.environmentObject(app)
}
}
}

一旦 SwiftUI 使用同步的领域,我也会打开本地领域。

struct MainScreenSync: View{
@EnvironmentObject var app: RealmSwift.App
//    @Environment(.realm) var syncedRealm
@ObservedResults(Item.self) var syncedItems

var body: some View {
VStack {
MainScreen()
Text(app.currentUser?.description ?? "not logged in")
}
.onAppear {
if let localRealm = try? Realm(), let user = app.currentUser {
let localItems = localRealm.objects(Item.self)
for item in localItems {
// local -> synced
let syncedItem = Item(value: item)
syncedItem.userId = user.id
$syncedItems.append(syncedItem)
// delete local
try? localRealm.write {
localRealm.delete(item)
}
}
}
}
}
}

链接

可能有一种更干净的方法可以做到这一点,但我只需从本地域复制项目,添加用户 ID,写入同步的领域,然后从本地域中删除。

文档中有一个页面解释了边缘情况。我希望他们能为我们处理这件事。

相关内容

  • 没有找到相关文章

最新更新