Swift使用RealmSwift创建Object时触发EXC_BAD_ACCESS错误(已更新配置)
RealmSwift 频繁触发 EXC_BAD_ACCESS 错误
我已修正Realm的配置定义,但仍出现错误。使用Swift和RealmSwift开发小型App时,写入数据库有时可行,但读取对象时频繁触发Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)错误。
RealmManager类(创建Realm实例)
import RealmSwift import Foundation class RealmManager { private var configured: Bool private var init(){ self.configured = false } static let shared = RealmManager() lazy var realm: Realm = { if !self.configured { var config = Realm.Configuration.defaultConfiguration let realm = try! Realm(configuration: config) } else { let realm = try! Realm() } return realm } func configure() throws { let dbName = "MyApp.realm" var dbConf = Realm.Configuration() guard let url = dbConf.fileURL?.deletingLastPathComponent().appendingLastPathComponent(dbName) else { throw DBError.databaseNameError } dbConf.fileURL = url dbConf.readOnly = false dbConf.schemaVersion = 1 do { self.realm = try Realm(configuration: dbConf) self.configured = true } catch { throw DBError.configurationError } }
AppDelegate中调用RealmManager的代码
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate { var window: UIWindow var realmM: Realm! var pushToken: String = "" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions : [UIApplication.LaunchOptionsKey: Any]?)-> Bool { self.realmM = openRealm() return true } private func openRealm() -> Realm { do { try RealmManager.shared.configure() } catch { print("Didnt configure Realm") } let realm = RealmManager.shared.realm return realm } }
触发错误的Realm Object定义
import Foundation import RealmSwift class Carga: Object{ @Persisted(primaryKey: true) var idCarga : Int32 @Persisted var idPedido : Int32 @Persisted var units : Int32 @Persisted var packages : Int32 @Persisted var kilograms : Double convenience init(_id: Int32, idPedido: Int32, uds: Int32, pkgs: Int32, kgs: Double) { self.init() self.idCarga = _id self.idPedido = idPedido self.units = uds self.packages = pkgs self.kilograms = kgs } } class Pedido : Object{ @Persisted(primaryKey: true) var idPedido : Int32 @Persisted var idLugar : Int32 @Persisted var cargas = RealmSwift.List<Carga>() // Thread 1: EXC_BAD_ACCESS (code=1,adress=0x0) convenience init(_id: Int32, idLugar: Int32, listCargas: RealmSwift.List<Carga>) { self.init() self.idPedido = _id self.idLugar = idLugar self.cargas = listCargas } } class Lugar : Object{ @Persisted(primaryKey: true) var idLugar : Int32 @Persisted var name : String @Persisted var pedidos = RealmSwift.List<Pedido>() // Thread 1 :EXC_BAD_ACCESS (code=1,adress=0x0) convenience init(_id: Int32, name: String, listPedidos: RealmSwift.List<Pedido>) { self.init() self.idLugar = _id self.name = name self.pedidos = listPedidos } }
补充说明
- ID定义为Int32是为了适配Firebase的Int32格式。
- 错误出现的执行路径:
- RealmManager中
self.realm = try Realm(configuration: dbConf) - Realm类的
Realm.init() - RLMObjectSchema的
getProperties(_:) - Object初始化(
Pedido.init()、Carga.init()) - Object属性定义(
@Persisted var cargas = RealmSwift.List<Carga>()等)
- RealmManager中
问题分析与解决方案
1. RealmManager核心错误修正
你的realm懒加载闭包存在两个致命问题:闭包内创建的realm是局部变量,未返回导致野指针;直接给self.realm赋值破坏懒加载逻辑。修正后代码:
import RealmSwift import Foundation enum DBError: Error { case databaseNameError case configurationError } class RealmManager { private var configured: Bool = false private(set) var realm: Realm? static let shared = RealmManager() private init() {} func configure() throws { let dbName = "MyApp.realm" var dbConf = Realm.Configuration() guard let url = dbConf.fileURL?.deletingLastPathComponent().appendingPathComponent(dbName) else { throw DBError.databaseNameError } dbConf.fileURL = url dbConf.readOnly = false dbConf.schemaVersion = 1 dbConf.migrationBlock = { migration, oldSchemaVersion in if oldSchemaVersion < 1 {} } do { self.realm = try Realm(configuration: dbConf) self.configured = true } catch { throw DBError.configurationError } } }
2. AppDelegate调用逻辑优化
避免访问未配置的Realm实例,增加空值判断:
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate { var window: UIWindow? var realmM: Realm? var pushToken: String = "" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions : [UIApplication.LaunchOptionsKey: Any]?)-> Bool { self.realmM = openRealm() return true } private func openRealm() -> Realm? { do { try RealmManager.shared.configure() return RealmManager.shared.realm } catch { print("Realm配置失败: \(error)") return nil } } }
3. Realm Object定义修复
@Persisted修饰的List无需手动初始化,便利初始化器中不能直接赋值List,需通过append添加元素:
import Foundation import RealmSwift class Carga: Object{ @Persisted(primaryKey: true) var idCarga: Int32 @Persisted var idPedido: Int32 @Persisted var units: Int32 @Persisted var packages: Int32 @Persisted var kilograms: Double convenience init(_id: Int32, idPedido: Int32, uds: Int32, pkgs: Int32, kgs: Double) { self.init() self.idCarga = _id self.idPedido = idPedido self.units = uds self.packages = pkgs self.kilograms = kgs } } class Pedido : Object{ @Persisted(primaryKey: true) var idPedido: Int32 @Persisted var idLugar: Int32 @Persisted var cargas: RealmSwift.List<Carga> convenience init(_id: Int32, idLugar: Int32, listCargas: [Carga]) { self.init() self.idPedido = _id self.idLugar = _id self.cargas.append(contentsOf: listCargas) } } class Lugar : Object{ @Persisted(primaryKey: true) var idLugar: Int32 @Persisted var name: String @Persisted var pedidos: RealmSwift.List<Pedido> convenience init(_id: Int32, name: String, listPedidos: [Pedido]) { self.init() self.idLugar = _id self.name = name self.pedidos.append(contentsOf: listPedidos) } }
4. 额外注意事项
- 所有Realm操作必须在同一线程执行,实例和对象不能跨线程访问。
- 写入操作必须放在
try! realm.write { }闭包内。 - 可添加错误监听辅助排查:
Realm.Configuration.defaultConfiguration.errorHandler = { error, isFatal in print("Realm错误: \(error), 是否致命: \(isFatal)") }
内容的提问来源于stack exchange,提问作者DMarMon
相关产品推荐
相关产品推荐

