You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多用户Realm数据库切换用户后查询结果未更新问题排查

解决Realm切换用户后数据未更新的问题

你的问题根源在于RealmServices单例中的userID和realm属性是在类初始化时就固定下来的,而单例只会被创建一次。当你切换用户时,单例已经存在,这些属性并不会自动更新到新用户的信息,所以你操作的依然是之前用户的Realm文件,自然查询结果还是旧数据。

问题代码分析

看你的代码:

let userID = Auth.auth().currentUser!.uid
var realm = try! Realm(configuration: Realm.Configuration.init(
    fileURL: Realm.Configuration().fileURL!.deletingLastPathComponent().appendingPathComponent("\(Auth.auth().currentUser!.uid).realm")))

这两个属性是存储属性,在RealmServices.shared第一次被调用时就会赋值,对应的是当时登录的用户。后续切换用户后,这两个值不会自动刷新,realm实例依然指向旧用户的Realm文件。

修复方案

我们需要让realm实例能够跟随当前登录用户动态更新,同时避免强制解包带来的崩溃风险。这里提供两种可行的修改方式:

方式1:将realm改为动态计算属性

每次访问realm时,都基于当前用户的UID重新生成配置并获取Realm实例(Realm内部会缓存实例,不会重复创建):

import Foundation
import RealmSwift
import Firebase

class RealmServices {
    private init() {}
    static let shared = RealmServices()
    
    // 动态获取当前用户UID,处理未登录情况
    private var currentUserID: String? {
        Auth.auth().currentUser?.uid
    }
    
    // 动态生成当前用户的Realm实例
    var realm: Realm {
        guard let uid = currentUserID else {
            fatalError("Attempted to access Realm without a logged-in user.")
            // 你也可以根据业务需求返回nil或抛出错误,而不是fatalError
        }
        
        let fileURL = Realm.Configuration.defaultConfiguration.fileURL!
            .deletingLastPathComponent()
            .appendingPathComponent("\(uid).realm")
        
        let config = Realm.Configuration(fileURL: fileURL)
        
        do {
            return try Realm(configuration: config)
        } catch {
            post(error)
            fatalError("Failed to initialize Realm: \(error.localizedDescription)")
        }
    }
    
    // 以下是你原有的create/update/delete等方法,保持不变
    func create<T:Object> (_ object: T) {
        do {
            try realm.write {
                realm.add(object)
            }
        } catch {
            post(error)
        }
    }
    
    func update <T: Object>(_ object: T, with dictionary: [String : Any?]) {
        do {
            try realm.write {
                for (key,value) in dictionary {
                    object.setValue(value, forKey: key)
                }
            }
        } catch {
            post(error)
        }
    }
    
    func delete<T:Object> (_ object: T) {
        do {
            try realm.write{
                realm.delete(object)
            }
        } catch {
            post(error)
        }
    }
    
    func post (_ error: Error) {
        NotificationCenter.default.post(name: NSNotification.Name("RealmError"), object: error)
    }
    
    func observeRealmErrors (in vc: UIViewController, completion: @escaping (Error?)-> Void) {
        NotificationCenter.default.addObserver(forName: NSNotification.Name("RealmError"), object: nil, queue: nil) { (Notification) in
            completion(Notification.object as? Error)
        }
    }
    
    func stopObservingError (in vc: UIViewController){
        NotificationCenter.default.removeObserver(vc, name: NSNotification.Name("RealmError"), object: nil)
    }
}

方式2:手动触发Realm配置更新(更可控)

如果希望更明确地控制Realm实例的生命周期,可以添加一个配置方法,在用户登录/切换时手动调用:

import Foundation
import RealmSwift
import Firebase

class RealmServices {
    private init() {}
    static let shared = RealmServices()
    
    private var _realm: Realm?
    
    // 对外暴露的Realm实例,确保已配置
    var realm: Realm {
        guard let realm = _realm else {
            fatalError("Realm not configured. Call configureRealmForCurrentUser() first.")
        }
        return realm
    }
    
    // 配置当前用户的Realm实例
    func configureRealmForCurrentUser() {
        guard let uid = Auth.auth().currentUser?.uid else {
            fatalError("No logged-in user found to configure Realm.")
        }
        
        let fileURL = Realm.Configuration.defaultConfiguration.fileURL!
            .deletingLastPathComponent()
            .appendingPathComponent("\(uid).realm")
        
        let config = Realm.Configuration(fileURL: fileURL)
        
        do {
            // 先销毁旧的Realm实例,避免资源泄漏
            _realm?.invalidate()
            _realm = try Realm(configuration: config)
        } catch {
            post(error)
            fatalError("Failed to configure Realm: \(error.localizedDescription)")
        }
    }
    
    // 原有的create/update/delete等方法保持不变...
}

使用时,在用户登录成功或切换用户后,调用:

RealmServices.shared.configureRealmForCurrentUser()
// 同时刷新TableView数据
yourTableView.reloadData()

额外注意事项

  1. 避免强制解包:原代码中Auth.auth().currentUser!.uid存在崩溃风险,建议添加未登录状态的处理逻辑。
  2. 刷新UI:切换用户后,一定要调用tableView.reloadData(),让TableView重新从新的Realm实例中获取数据。
  3. Realm实例生命周期:如果使用方式2,记得在用户登出时调用_realm?.invalidate(),释放资源。

内容的提问来源于stack exchange,提问作者Radu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:07:06