Swift 6迁移中Realm Non-sendable警告无法消除,求解决方案
解决Swift 6迁移中Realm的Non-sendable警告问题
问题原因
Realm的Realm类型本身并未实现Sendable协议,添加@preconcurrency import RealmSwift仅允许在并发上下文调用Realm的异步API,无法改变Realm实例的非Sendable属性。Swift 6的严格并发检查会阻止非Sendable类型跨actor边界传递,因此触发警告。
解决方案
方案1:封装Realm访问,避免暴露实例(推荐)
不直接将Realm实例暴露给actor外部,而是通过封装好的方法提供数据操作能力,彻底规避跨actor传递非Sendable类型的问题。
修改后的代码示例:
@preconcurrency import RealmSwift import Foundation // 定义错误类型 enum StorageError: Error { case initialize } @StorageActor protocol StorageProtocol: Sendable { // 移除直接返回Realm的属性,替换为具体操作方法 func fetchObjects<T: Object>(_ type: T.Type) throws -> Results<T> func addObject<T: Object>(_ object: T) throws } final class Storage: StorageProtocol, @unchecked Sendable { private var realm: Realm? @StorageActor public init(_ name: String) async throws { var config = Realm.Configuration.defaultConfiguration guard var fileURL = config.fileURL else { throw StorageError.initialize } fileURL.deleteLastPathComponent() fileURL.appendPathComponent(name) fileURL.appendPathExtension("realm") config.fileURL = fileURL print(config.fileURL?.absoluteString ?? "") realm = try await Realm(configuration: config, actor: StorageActor.shared) } // 实现封装的操作方法 func fetchObjects<T: Object>(_ type: T.Type) throws -> Results<T> { guard let realm = realm else { throw StorageError.initialize } return realm.objects(type) } func addObject<T: Object>(_ object: T) throws { guard let realm = realm else { throw StorageError.initialize } try realm.write { realm.add(object) } } } @globalActor actor StorageActor: GlobalActor { static public var shared = StorageActor() }
方案2:标记Realm为@unchecked Sendable(需谨慎)
如果必须暴露Realm实例,可通过扩展手动标记Realm为@unchecked Sendable,但必须严格保证所有对该Realm实例的访问都在StorageActor上下文中执行,否则会引发线程安全问题。
添加以下扩展:
extension Realm: @unchecked Sendable {}
同时保留原代码中@StorageActor对realm属性的修饰,确保访问范围被限制在指定actor内。
注意事项
- 方案1符合Swift并发模型设计原则,是最安全的做法,彻底隔离了Realm实例的访问范围。
- 方案2存在风险,Realm实例并非线程安全,必须确保所有操作都在
StorageActor中执行,不能在其他线程或actor中直接调用该实例的方法。
内容的提问来源于stack exchange,提问作者Hattori Hanzō
相关产品推荐
相关产品推荐

