Преобразование локальной области в синхронизированную область в середине жизненного цикла приложения (в 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)
                    }
                }
            }
        }
    }
}

связь

Вероятно, есть более чистый способ сделать это, но я просто копирую элементы из локальной области, добавляю идентификатор пользователя, записываю в синхронизированную область, а затем удаляю из локальной области.

В документации есть страница , объясняющая крайние случаи.Я бы хотел, чтобы они справились с этим за нас.

Другие вопросы по тегам