3

基本上,我想处理任何设备都获得SyncError类型的情况ClientResetError,希望我的设备再次重新登录到领域。但根据文档,closeRealmSafely在我再次登录领域之前,我们必须这样做,但我不确定如何安全地关闭领域。

我正在阅读文档(https://docs.realm.io/sync/using-synced-realms/errors#client-reset)来处理客户端重置错误,发现它非常混乱。我需要帮助了解以下代码。

  1. 首先,没有可用的方法来安全地关闭Realm。请帮助我了解如何安全地关闭领域?
  2. 我如何备份以及何时使用它?我是否应该跳过重置错误,因为在文档中提到如果未手动启动客户端重置过程,它将在下一次启动应用程序后自动发生,在首次访问 SyncManager 单例时。如果需要,应用程序负责保存备份副本的位置,以便以后可以找到备份副本。”

下面是文档中的错误处理程序示例代码。

 let syncError = error as! SyncError
 switch syncError.code {
 case .clientResetError:
 if let (path, clientResetToken) = syncError.clientResetInfo() {
 closeRealmSafely()
 saveBackupRealmPath(path)
 SyncSession.immediatelyHandleError(clientResetToken)
 }
 default:
 // Handle other errors...
 ()
 }
}```
4

1 回答 1

3

最后我们弄清楚了如何处理客户端重置错误。我们已采取以下步骤来避免数据丢失,以防用户离线并上线并出现重置错误。

  1. 将本地领域保存到另一个目录

  2. 使领域无效并为零

  3. 启动领域手动重置 - 调用传递SyncSession.immediatelyHandleErrorclientResetToken它将从目录中删除现有领域

  4. 显示客户端重置警报 - 这将提示用户重新启动应用程序。

  5. 在下一次启动时,领域会从 ROS 中创建一个新领域。

  6. 新领域连接后,从上面备份目录中保存的旧领域恢复领域记录(如果有)。

  7. 从目录中删除备份领域(旧领域)。

     switch syncError.code {
     case .clientResetError:
     if let (path, clientResetToken) = syncError.clientResetInfo() {
     // taking backup
     backUpRealm(realm: yourLocalRealm)
     // making realm nil and invalidating
     yourLocalRealm?.invalidate()
     yourLocalRealm = nil
    //Initiate realm manual reset  - Call `SyncSession.immediatelyHandleError` with `clientResetToken` passed and it will delete the existing realm from directory
     SyncSession.immediatelyHandleError(clientResetToken)
     // can show alert to user to relaunch the app
     showAlertforAppRelaunch()
     }
     default:
     // Handle other errors...
     ()
     }
    }```
    
    

备份领域代码如下所示:

func backUpRealm(realm: Realm?) {
        do {
            try realm?.writeCopy(toFile: backupUrl)
        } catch {
            print("Error backing up data")
        }
    }

完成此备份后,备份路径将可用。在下一次启动时,设备将连接并从 ROS 下载新领域,因此在设备连接后,从备份路径中保存的备份领域恢复领域记录。

还原合并备份代码将如下所示。在重新启动后连接领域时放置以下方法。 ```restoredRealm` 是启动时新下载的领域

func restoreAndMergeFromBackup(restoredRealm: Realm?) {
        let realmBackUpFilePath = isRealmBackupExits()
        // check if backup exists or not
        if realmBackUpFilePath.exists {
            let config = Realm.Configuration(
                fileURL: URL(fileURLWithPath: realmBackUpFilePath.path),
                readOnly: true)
            
            let realm = try? Realm(configuration: config)
            
            guard let backupRealm = realm else { return }
            
            //Get your realm Objects
            let objects = backupRealm.objects(YourRealmObject.self)
            
           try? restoredRealm?.safeWrite {
        
                for object in objects {
                // taking local changes to the downloaded realm if it has
                    restoredRealm?.create(YourRealmObject.self, value: object, update: .modified)
                }

                self.removeRealmFiles(path: realmBackUpFilePath.path)
            }
        } else {
            debug("backup realm does not exists")
        }
    }
    
    private func isRealmBackupExits() -> (exists: Bool, path: String) {
        let documentsPath = URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
        
        let realmPathComponent =  documentsPath.appendingPathComponent("your_backup.realm")
        
        let filePath = realmPathComponent.path
        let fileManager = FileManager.default
        
        if fileManager.fileExists(atPath: filePath) {
            return (true, filePath)
        }
        
        return (false, "")
    }


    private func removeRealmFiles(path: String) {
        let realmURL = URL(fileURLWithPath: path)
        
        let realmURLs = [
            realmURL,
            realmURL.appendingPathExtension("lock"),
            realmURL.appendingPathExtension("realm"),
            realmURL.appendingPathExtension("management")
        ]
        for URL in realmURLs {
            do {
                try FileManager.default.removeItem(at: URL)
            } catch {
                debug("error while deleting realm urls")
            }
        }
    }```

在我们的测试中,我们发现领域会自动进行备份,因此出于安全目的我们将其删除。您将获得的路径参数if let (path, clientResetToken) = syncError.clientResetInfo()

func removeAutoGeneratedRealmBackUp(path: String) {
    do {
        try FileManager.default.removeItem(at: URL(fileURLWithPath: path))
    } catch {
        debug("error while deleting realm backUp path \(path)")
    }
} 
于 2020-08-26T08:20:26.980 回答