Realm iOS: как выполнить сброс клиента
По сути, я хочу разобраться в случае, когда любое устройство SyncError
с типом ClientResetError
затем я хочу, чтобы мое устройство снова вошло в систему. но согласно документации, мы должныcloseRealmSafely
прежде чем я снова войду в область, но я не уверен, как безопасно закрыть область.
Я просматриваю документ (https://docs.realm.io/sync/using-synced-realms/errors), чтобы обработать ошибку сброса клиента, и обнаружил, что это очень сбивает с толку. Мне нужна помощь в понимании следующего кода.
- Во-первых, нет доступного метода closeRealmsafely. Пожалуйста, помогите мне понять, как я могу безопасно закрыть область?
- Как сделать резервную копию и когда я буду ее использовать? Должен ли я пропустить ошибку сброса, потому что в документации упоминается , что процесс сброса клиента не запускается вручную, вместо этого он автоматически произойдет после следующего запуска приложения при первом доступе к синглтону 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...
()
}
}```
2 ответа
Finally we figured out how to handle the client reset error. We have taken following steps To avoid the data loss incase user is offline and came online and got reset error.
Save the local realm to another directory
Invalidate and nil the realm
Initiate realm manual reset - Call
SyncSession.immediatelyHandleError
withclientResetToken
passed and it will delete the existing realm from directoryShow client reset alert - This will intimate user to relaunch the app.
On next launch realm creates a fresh realm from ROS.
After new realm connects, restore the realm records (if any) from the old realm saved in backup directory above.
Delete the backup realm(old realm) from directory.
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... () } }```
The back up realm code look like this:
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)")
}
}
Для других людей, которых смущает эта тема или которые ищут дополнительную информацию, есть репозиторий MongoDB Realm GitHub с образцом кода для лучших практик Realm, включая сброс клиента. (По крайней мере, для iOS и JS).