创建 RealmSwift 对象时 Realm Swift EXC_BAD_ACCESS

问题描述 投票:0回答:1

更新:我更新了对领域定义的更正,但仍然收到错误。

我正在使用 Swift 和 RealmSwift 构建我的小型应用程序,但在尝试使其工作时遇到多个错误。我得到的错误主要来自尝试从数据库读取对象,因为写入它们有时似乎有效。我之前问过一个问题,该问题通过设置领域对象的方法得到了回答,但现在我收到此 EXC_BAD_ACCESS 错误。让我们从我的 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 类中调用该类:

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
  }
}

现在这就是我声明 3 个对象的方式,其中我收到了 EXC_BAD_ACCESS 错误:

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 格式读取的。
  • 错误 Thread1: EXC_BAD_ACCESS(code=1,address=0x0) 在以下几行中抛出:

1-来自 RealmManager

self.realm = 尝试 Realm(配置:dbConf)

2-来自领域类

Realm.init()

3-RLMObjectSchema 类属性

获取属性(_:)

4-从对象初始化

Pedido.init()

Carga.init()

5- 从对象属性

@Persisted var cargas = RealmSwift.List()

@Persisted var pedidos = RealmSwift.List()

请勿编译此代码块。它只是 Thread1 在创建 Realm 实例时遵循的路径以及错误发生位置的表示。

ios swift realm
1个回答
0
投票

我相信错误在于 Realm 的配置方式以及调用它的时间(AppDelegate?),而不是对象本身。

您似乎正在尝试创建一个在整个应用程序中持续存在的领域变量,这通常不是最佳实践。 Realm 不是线程安全的,对象和应用程序函数可以在不同的线程上运行;这会导致您看到的错误类型。

最佳实践是在需要时实例化 Realm 对象,或者按照下面的示例通过单例模式实例化。经验法则是,最好按需创建 Realm 实例,而不是提前抢先创建实例并保留它

调用Realm(configuration:)时,Realm本身会在内部进行缓存 该对象并将在每次后续调用时返回相同的对象。 该对象保留在缓存中,直到它被自动释放池 创建于已耗尽。 ——来自这个答案

我将使用问题中三个对象(复制和粘贴)的代码(请参阅此答案的底部)

然后,我将采用对一个单独问题的回答中的一些代码并对其进行修改,以将Realm文件写入我的Mac桌面(iOS功能类似)。您可以将 URL 指向适合您的用例的任何位置。这个

RealmService
是一个单例,应该放置在任何其他类之外。

class RealmService {
    private init() {}

    static let shared = RealmService()

    lazy var realm: Realm = {
        //modify below to be your iOS URL/path
        let manager = FileManager()
        let homeURL = manager.homeDirectoryForCurrentUser
        let desktopURL = homeURL.appendingPathComponent("Desktop")
        let pathToThisRealmFile = desktopURL.appendingPathComponent("desktopRealm.realm")
        //modify above to be your iOS URL/path

        var config = Realm.Configuration.defaultConfiguration
        config.fileURL = pathToThisRealmFile
        let realm = try! Realm.init(configuration: config)
        return realm
    }()
}

请注意,我没有从我的 AppDelegate 调用任何代码,因为没有理由这样做。 RealmService 仅在与 Realm 交互时才需要引用。请注意,此代码适用于本地领域;同步领域可以/应该以不同的方式处理。

然后是实例化和写入三个对象的代码;卡尔加、佩迪多和卢加尔。我在 UI 中添加了一个按钮,单击该按钮会在我的桌面领域中创建三个对象。

func handleButtonClick() {
    let a = Pedido()
    let b = Lugar()
    let c = Carga()

    let realm = RealmService.shared.realm
    try! realm.write {
        realm.add(a)
        realm.add(b)
        realm.add(c)
    }
}

运行此代码并单击按钮,我的桌面上会出现三个文件; DesktopRealm.realm、desktopRealm.realm.lock、desktopRealm.realm.management(这是一个文件夹)。

经检查,desktopRealm.realm 文件包含预期的三个对象。


问题中的领域对象

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: 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>()

  convenience init(_id: Int32, name: String, listPedidos: RealmSwift.List<Pedido>) {
    self.init()
    self.idLugar = _id
    self.name = name
    self.pedidos = listPedidos
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.