Swift使用MongoDB+Realm开发注册后Realm无用户导致空异常问题
问题核心原因
你遇到的报错本质是Atlas触发器异步执行和客户端登录流程的时序差:
Realm Auth创建用户账号的操作是同步完成的,注册成功后你立刻执行登录、打开对应分区Realm的操作,但是绑定的用户创建触发器是后台异步执行的,存在几十到几百毫秒的延迟,很可能你打开Realm完成首次同步时,触发器还没把User文档写入Atlas集群,导致本地Realm中没有User对象,强制解包直接抛出nil异常。
修复方案
第一步:先修复强制解包的安全隐患
首先修改hasSignedConsent方法的写法,避免无意义的强制解包,哪怕数据未同步也不会直接崩溃:func hasSignedConsent(realmA: Realm) -> Bool { guard let user = realmA.objects(User.self).first else { // 未获取到用户数据时默认返回false,可根据业务需求调整 return false } return user.hasSignedConsent }第二步:开启Realm首次同步等待配置
Realm.asyncOpen默认只要本地Realm文件创建完成就会返回,不会等待服务端数据全量同步完成,你需要在构造配置时开启首次同步等待参数,确保返回的Realm已经拉取到服务端所有已有数据:var configuration = user.configuration(partitionValue: "user=\(user.id)") configuration.objectTypes = RealmManager.OBJECT_TYPES // 新增此行配置,要求首次打开Realm必须等待服务端同步完成 configuration.waitForInitialSync = true该配置仅对首次打开Realm生效,后续打开会优先使用本地缓存,不会增加额外耗时。
第三步:添加极端场景兜底重试逻辑
如果开启上述配置后仍偶现问题(比如网络波动导致触发器执行延迟过高),可以在拿到Realm实例后添加短时间轮询判断,等待User对象写入完成再走后续流程:case .success(let userRealm): var retryCount = 0 func checkUserExists() { if userRealm.objects(User.self).first != nil { // 已有用户数据,执行原有业务逻辑 RealmManager.shared.setRealm(realm: userRealm, handler:{ if RealmManager.shared.hasSignedConsent(realmA: userRealm){ self?.scheduleReminders() self?.goToViewController(storyboardID: "Main", viewcontrollerID: "home") } else { self?.goToViewController(storyboardID: "Onboarding", viewcontrollerID: "consentVC") } }) } else if retryCount < 6 { // 最多等待3秒,每500毫秒重试一次 retryCount += 1 DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: checkUserExists) } else { // 超时后的错误提示逻辑,可自行调整 self.errorLabel.text = "用户数据加载失败,请重试" } } checkUserExists()第四步:校验触发器执行状态
可以进入Atlas App Services的日志面板,查看用户创建触发器的执行记录,排除触发器本身执行报错、没有成功写入User文档的情况。
内容的提问来源于stack exchange,提问作者Negar Bean
相关产品推荐
相关产品推荐

