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

如何打造跨线程无崩溃的Realm包装器并优化性能

解决方案

1. 线程专属Realm实例缓存

Realm实例不支持跨线程复用,这是你之前缓存全局实例崩溃的核心原因。正确的做法是为每个线程单独缓存Realm实例,利用Thread.current.threadDictionary存储当前线程的专属实例:

import Foundation
import RealmSwift
import Realm

class RealmStorage: LocalStoring {
    private static let configuration: Realm.Configuration = {
        let schemaString = Bundle.main.object(forInfoDictionaryKey: "Realm Schema") as? String ?? ""
        let schema = UInt64(schemaString) ?? 1
        return Realm.Configuration(schemaVersion: schema)
    }()
    private let category: String
    init(category: String) {
        self.category = category
    }
    
    // 获取当前线程的专属Realm实例
    private func realmForCurrentThread() throws -> Realm {
        let threadKey = "RealmStorage_\(category)"
        let threadDictionary = Thread.current.threadDictionary
        
        if let existingRealm = threadDictionary[threadKey] as? Realm {
            return existingRealm
        }
        
        let newRealm = try Realm(configuration: RealmStorage.configuration)
        threadDictionary[threadKey] = newRealm
        return newRealm
    }
    
    // 修改原有方法,使用线程专属实例
    func store<T: Object>(_ object: T) {
        do {
            let realm = try realmForCurrentThread()
            try realm.write {
                realm.add(object, update: .all)
            }
        } catch {
            print("Realm error: \(error.localizedDescription)")
        }
    }
    
    func update<T: Object>(_ object: T, value: Any?, for key: String) {
        do {
            let realm = try realmForCurrentThread()
            try realm.write {
                object.setValue(value, forKey: key)
            }
        } catch {
            print("Realm error: \(error.localizedDescription)")
        }
    }
    
    func retrieve<T: Object>(_ objectType: T.Type) -> [T] {
        guard let realm = try? realmForCurrentThread() else {
            return []
        }
        let objects = realm.objects(objectType.self)
        return Array(objects)
    }
    
    func remove<T: Object>(_ objectType: T.Type,
                           where condition: @escaping (T) -> Bool) {
        do {
            let realm = try realmForCurrentThread()
            try realm.write {
                let objects = realm.objects(objectType.self).filter(condition)
                realm.delete(objects)
            }
        } catch {
            print("Realm error: \(error.localizedDescription)")
        }
    }
    
    func removeAll<T: Object>(_ objectType: T.Type) {
        do {
            let realm = try realmForCurrentThread()
            try realm.write {
                let objects = realm.objects(objectType.self)
                realm.delete(objects)
            }
        } catch {
            print("Realm error: \(error.localizedDescription)")
        }
    }
}

这个方案既避免了跨线程崩溃,又不用每次操作都重新初始化Realm,能有效提升性能。

2. 预加载Realm减少初始化开销

在App启动时提前初始化主线程的Realm实例,让Realm提前完成文件加载和schema校验,后续主线程操作会更流畅:

// 在AppDelegate或SceneDelegate的启动方法中添加
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    do {
        // 预加载主线程Realm实例
        _ = try Realm(configuration: RealmStorage.configuration)
    } catch {
        print("Realm preload error: \(error.localizedDescription)")
    }
    return true
}

3. 批量合并操作

如果存在多个连续的数据操作,合并到同一个Realm write块中,减少实例初始化次数:

// 新增批量存储方法
func storeBatch<T: Object>(_ objects: [T]) {
    do {
        let realm = try realmForCurrentThread()
        try realm.write {
            objects.forEach { realm.add($0, update: .all) }
        }
    } catch {
        print("Realm batch error: \(error.localizedDescription)")
    }
}

4. 异步操作优化体验

对于耗时的读写操作,使用Realm的异步API,避免阻塞主线程,同时Realm内部会优化实例复用:

// 新增异步存储方法
func storeAsync<T: Object>(_ object: T, completion: ((Error?) -> Void)?) {
    Realm.asyncOpen(configuration: RealmStorage.configuration) { result in
        switch result {
        case .success(let realm):
            do {
                try realm.write {
                    realm.add(object, update: .all)
                }
                completion?(nil)
            } catch {
                completion?(error)
            }
        case .failure(let error):
            completion?(error)
        }
    }
}

不推荐双数据源方案:内存数组+Realm的组合很容易出现数据不一致(比如异步操作未同步、线程竞态),会增加调试和维护成本,上述方案更稳定可靠。

内容的提问来源于stack exchange,提问作者Bawenang Rukmoko Pardian Putra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:34:57