Преобразование локальной области в синхронизированную область в середине жизненного цикла приложения (в Swift)
Мое приложение будет иметь платную функцию под названием синхронизация нескольких устройств. Я хотел бы реализовать функцию с Realm Cloud - Query Based Sync.
Благодаря этой теме я знаю, как преобразовать локальную область в синхронизированную область.
Но это основано на сценарии, при котором пользователи синхронизируют свою область с самого начала приложения - до открытия своей несинхронизированной локальной области. Это не работает для меня, потому что мои пользователи начнут синхронизацию, когда они заплатят за это.
Поэтому я должен преобразовать их локальное Царство в середине жизненного цикла приложения, и к этому времени локальное Царство уже открыто.
Моя проблема возникает здесь. Когда я пытаюсь преобразовать локальную область в синхронизированную, приложение вылетает с таким сообщением:
Область по пути "…" уже открыта с разными разрешениями на чтение.
Я пытался найти способ закрыть локальное Царство перед его преобразованием, но какао Царства не позволяет мне программно закрыть Царство.
Вот мой код, преобразовывающий локальную область в синхронизированную область.
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)
}
}
}
}
Любая помощь будет оценена. Благодарю.
2 ответа
Я сделал копию файла локальной области и открыл копию с помощью RLMRealmConfiguration. После этого просто удалите оба файла. Не лучшее решение, но работает
Я думаю, что лучший подход — иметь два мира. В моем случае я использую 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)
}
}
}
}
}
}
Вероятно, есть более чистый способ сделать это, но я просто копирую элементы из локальной области, добавляю идентификатор пользователя, записываю в синхронизированную область, а затем удаляю из локальной области.
В документации есть страница , объясняющая крайние случаи.Я бы хотел, чтобы они справились с этим за нас.