领域iOS:如何处理客户端重置

领域iOS:如何处理客户端重置,ios,swift,realm,realm-mobile-platform,mongodb-realm,Ios,Swift,Realm,Realm Mobile Platform,Mongodb Realm,基本上,我想处理这样一种情况:任何设备都使用ClientResetError类型获得了SyncError,然后,我想让我的设备重新登录到realm。但根据文档,我们必须在再次登录realm之前安全地关闭realm,但我不确定如何安全地关闭realm 我正在通过doc()处理客户端重置错误,发现它非常混乱。我想帮助您了解以下代码 首先,没有可用于关闭RealmSafey的方法。请帮助我了解如何安全关闭该领域 如何备份以及何时使用它?我是否应该跳过重置错误,因为在文档中提到如果客户端重置过程不是手动

基本上,我想处理这样一种情况:任何设备都使用
ClientResetError
类型获得了
SyncError
,然后,我想让我的设备重新登录到realm。但根据文档,我们必须在再次登录realm之前安全地关闭realm,但我不确定如何安全地关闭realm

我正在通过doc()处理客户端重置错误,发现它非常混乱。我想帮助您了解以下代码

  • 首先,没有可用于关闭RealmSafey的方法。请帮助我了解如何安全关闭该领域
  • 如何备份以及何时使用它?我是否应该跳过重置错误,因为在文档中提到如果客户端重置过程不是手动启动的,它将在下一次启动应用程序后,在首次访问SyncManager singleton时自动发生。如果需要,应用程序有责任保留备份副本的位置,以便以后可以找到备份副本。“
  • 下面是文档中的错误处理程序示例代码

     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...
     ()
     }
    }```
    

    最后,我们解决了如何处理客户端重置错误。我们采取了以下步骤,以避免在用户脱机和联机时出现重置错误而导致数据丢失

  • 将本地域保存到另一个目录

  • 使王国无效

  • 启动领域手动重置-调用
    SyncSession.instamelyhandleerror
    ,并传递
    clientResetToken
    ,它将从目录中删除现有领域

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

  • 在下一次启动时,realm从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自动进行了备份,因此出于安全目的,我们将其删除。如果let(path,clientResetToken)=syncError.clientResetInfo()


    我们谈论的是手动、受控的代码重置,还是设备在没有警告的情况下关闭的重置?是的,我谈论的是手动、受控的代码重置。基本上,我想处理一种情况,即任何设备获得类型为ClientResetError的SyncError,然后,希望我的设备重新登录到realm。但是根据文档,在我再次登录realm之前,我们必须安全地关闭realm,但我不确定如何安全地关闭realm。在这种情况下,当你的应用程序断开连接时,你必须删除你的本地领域(文件)然后,下一次应用程序启动时,服务器上的数据将重新下载并同步。重要的是,对领域对象的任何引用都将使领域保持活动状态,并且您将无法删除它。因此,在删除这些文件之前,最好确保您的应用程序未连接到领域。交叉发布到领域中的ForumsHanks Jay.Delet对本地域进行初始化可能会导致数据丢失。如何避免这种情况?打开错误代码会在代码中的何处?AppDelegate?
    func removeAutoGeneratedRealmBackUp(path: String) {
        do {
            try FileManager.default.removeItem(at: URL(fileURLWithPath: path))
        } catch {
            debug("error while deleting realm backUp path \(path)")
        }
    }