iOS版Realm:如何处理客户端重置

问题描述

基本上,我想处理一个情况,即任何设备的类型为SyncError的{​​{1}},然后希望我的设备重新登录以进入领域。但是根据文档,我们必须ClientResetError才能再次登录领域,但是我不确定如何安全地关闭领域。

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

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

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

closeRealmSafely

解决方法

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

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

  2. 使领域无效并无效

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

  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")
            }
        }
    }```

在测试中,我们发现realm自动创建了一个备份,因此出于安全目的将其删除。您将在if let (path,clientResetToken) = syncError.clientResetInfo()

中获得的path参数
func removeAutoGeneratedRealmBackUp(path: String) {
    do {
        try FileManager.default.removeItem(at: URL(fileURLWithPath: path))
    } catch {
        debug("error while deleting realm backUp path \(path)")
    }
} 

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...