问题描述
基本上,我想处理一个情况,即任何设备的类型为SyncError
的{{1}},然后希望我的设备重新登录以进入领域。但是根据文档,我们必须ClientResetError
才能再次登录领域,但是我不确定如何安全地关闭领域。
我正在检查文档(https://docs.realm.io/sync/using-synced-realms/errors#client-reset)来处理客户端重置错误,并发现它非常令人困惑。我需要帮助来了解以下代码。
- 首先,没有可用的方法来安全地关闭closeRealm。请帮助我了解如何安全地关闭领域?
- 如何备份以及何时使用?我是否应该跳过重置错误,因为在文档中提到如果未手动启动客户端重置过程,则它将在下次访问该应用程序后自动进行,首先访问SyncManager单例。如有必要,应用程序有责任保留备份副本的位置,以便以后可以找到备份副本。”
下面是文档中的错误处理程序示例代码。
closeRealmSafely
解决方法
最后,我们弄清楚了如何处理客户端重置错误。我们采取了以下步骤,以避免数据丢失,以防用户脱机并联机并出现重置错误。
-
将本地领域保存到另一个目录
-
使领域无效并无效
-
启动领域手动重置-通过传递
SyncSession.immediatelyHandleError
调用clientResetToken
,它将从目录中删除现有领域 -
显示客户端重置警报-这将提示用户重新启动应用。
-
在下一次启动时,领域会从ROS创建一个新领域。
-
新领域连接后,从保存在上面备份目录中的旧领域恢复领域记录(如果有)。
-
从目录中删除备份领域(旧领域)。
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")
}
}
}```
在测试中,我们发现realm自动创建了一个备份,因此出于安全目的将其删除。您将在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)")
}
}