UPDATE: I updated the correction of my definition of Realm, I still get the error.
I'm using Swift and RealmSwift to build my small App and I'm having multiple errors while trying to make it work. The errors I get are mainly from trying to read Objects from the database, since writing them seems to work sometimes. I asked a question previously which was answered with a way to set up the Realm Objects, but now I get this EXC_BAD_ACCESS error. Lets begin with my RealmManager class in which I create the Realm Instance.
我正在使用Swift和RealmSwift来构建我的小型应用程序,在尝试使其工作时出现了多个错误。我遇到的错误主要来自于试图从数据库中读取对象,因为有时编写对象似乎是可行的。我之前问过一个问题,这个问题的答案是设置Realm对象的方法,但现在我得到了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
}
}
Then I call the class from my AppDelegate class:
然后,我从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
}
}
Now this is how I declare 3 of my objects in which I get the EXC_BAD_ACCESS error:
下面是我如何声明我的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
}
}
- IDs are defined as Int32 because the value is read from Firebase Int32 format.
- The error Thread1: EXC_BAD_ACCESS(code=1,address=0x0) is thrown in the following lines:
1- From RealmManager
1-来自RealmManager
self.realm = try Realm(configuration: dbConf)
2- From Realm class
2-来自境界类
Realm.init()
3- RLMObjectSchema PropertiesForClass
3-RLMObjectSchema属性ForClass
getProperties(_:)
4- From the Object initialization
4-从对象初始化
Pedido.init()
Carga.init()
5- From the Object properties
5-从对象属性
@Persisted var cargas = RealmSwift.List()
@Persisted var pedidos = RealmSwift.List()
Do not compile this code block. It is just a representation of the pathing that the Thread1 is following when creating the Realm instance and where the error is happening.
不要编译此代码块。它只是Thread1在创建Realm实例时所遵循的路径以及错误发生的位置的表示。
更多回答
There's a typo in the Pedido class self.cargas = listaCargas
which should be listCargas
. I copy and pasted your three classes into a project and they all worked correctly. That would mean the issue lies in how Realm is being called or initialized. This is not a valid Realm config let configration = DBConfig(
and we don't know what that is specifically but all of that code could be replaced with about 8 lines so why not simplify it? It will make troubleshooting and maintaining much easier. Also, why are objectTypes
being defined?
Pedido类self.cargas=listaCargas中有一个拼写错误,应该是listCargas。我把你的三个类复制粘贴到一个项目中,它们都能正常工作。这意味着问题在于Realm是如何被调用或初始化的。这不是一个有效的Realm配置let configration=DBConfig(我们不知道具体是什么,但所有这些代码都可以用大约8行替换,所以为什么不简化它呢?这将使故障排除和维护更加容易。此外,为什么要定义objectTypes?
Oh, and for a design pattern, see this answer
哦,关于设计模式,请看这个答案
I dont know, I am following every answer you give me. Realm is confgured as you did in multiple answers and you also seem to have tested the code and it worked. So, why is my App throwing a Thread EXC_BAD_ACCESS when reading a RealmSwift.list with the persisted definition if it is the right way to do it? I am using Realm 10.42.1.
我不知道,我正在关注你给我的每一个答案。Realm的配置就像你在多个答案中所做的那样,你似乎也测试了代码,它起了作用。那么,如果这是正确的方法,为什么我的应用程序在读取带有持久化定义的RealmSwift.list时会抛出线程EXC_BAD_ACCESS呢?我正在使用Realm 10.42.1。
I never get an error on console its just the EXC_BAD_ACCESS that can't let my App to run
我从未在控制台上遇到错误,只是EXC_BAD_ACCESS无法让我的应用程序运行
I see there's an update to the code in your question; however, I cannot get it to compile. There are a number of syntax error's in the code and it's incomplete. As a test, visit the answer linked above, comment out all of your Realm code and replace it with the code in the question from the RealmService singleton solution. Use it exactly as written - copy and paste. Then add the code to create and write one of each of your objects. Do not create relationships or anything else. Just keep it simple like this let c = Carga()
and then get realm and write the object. Report back your findings.
我看到你的问题中有一个代码更新;但是,我无法编译它。代码中有许多语法错误,而且不完整。作为测试,请访问上面链接的答案,注释掉所有Realm代码,并将其替换为RealmService单例解决方案中的问题代码。如实使用——复制粘贴。然后添加代码来创建并编写每个对象中的一个。不要建立关系或其他任何事情。只需保持简单,如let c=Carga(),然后获取领域并编写对象。报告您的调查结果。
I believe the error lies in how Realm is configured and the timing of when it's called (AppDelegate?), not the objects themselves.
我认为错误在于Realm的配置方式和调用时间(AppDelegate?),而不是对象本身。
It seems that you're attempting to create a realm var that persists throughout the app and that's generally not best practice. Realm is not thread safe and objects and app function could run on different threads; that would cause the types of errors you're seeing.
你似乎试图创建一个在整个应用程序中持续存在的领域var,这通常不是最佳实践。Realm不是线程安全的,对象和应用程序功能可以在不同的线程上运行;这将导致您所看到的错误类型。
Best practice is to instantiate a Realm object when needed, or per the below example via a singleton pattern. Rule of thumb is it's better to create instances of Realm on demand rather than pre-emptively creating an instance ahead of time and retaining it
最佳实践是在需要时实例化Realm对象,或者按照下面的示例通过单例模式实例化。经验法则是,最好按需创建Realm实例,而不是先发制人地提前创建实例并保留它
When calling Realm(configuration:), Realm itself will internally cache
that object and will return the same object on each subsequent call.
The object remains in the cache until the autoreleasepool it was
created in is drained.
-- from this answer
I will use the code for the three objects (copy and pasted) from the question (see bottom of this answer)
我将使用问题中三个对象的代码(复制并粘贴)(见答案底部)
Then, i'll adopt some code from an answer to a separate question and modify it to write the Realm file to my Mac desktop (iOS functions are similar). You can point the URL to wherever fits your use case. This RealmService
is a singleton that should be placed outside of any other classes.
然后,我将采用一个单独问题的答案中的一些代码,并对其进行修改,将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
}()
}
Note that I am not calling any code from my AppDelegate as there's no reason to. The RealmService only needs to be referenced when you're interacting with Realm. Note this code is for local realm; a Sync'd realm can/should be handled differently.
请注意,我没有从我的AppDelegate调用任何代码,因为没有理由这样做。RealmService只需要在您与Realm交互时被引用。请注意,此代码适用于本地领域;同步领域可以/应该以不同的方式处理。
Then the code to instantiate and write three objects; a Carga, Pedido and Lugar. I added a button to my UI that when clicked, creates the three objects in my desktop Realm.
然后代码实例化并编写三个对象;a Carga、Peido和Lugar。我在我的UI中添加了一个按钮,当点击时,它会在我的桌面Realm中创建三个对象。
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)
}
}
This this code is run and the button is clicked, three files appear on my desktop; desktopRealm.realm, desktopRealm.realm.lock, desktopRealm.realm.management (which is a folder).
这个代码运行后,点击按钮,三个文件出现在我的桌面上;desktopRealm.realm、desktopRealm_realm.lock、desktopRealm.realm.management(这是一个文件夹)。
Upon inspection, the desktopRealm.realm file contains the three objects as expected.
经过检查,desktopRealm.realm文件包含预期的三个对象。
Realm Objects from question
问题中的领域对象
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
}
}
更多回答
I am sorry I tried both ways, my realm configuration and your realm configuration both stop my code in the same line. I figure this must be an issue with storing other Realm objects inside one Realm object. This database is not working for me and I am replicating the error, showing my code and there's no active support from Realm developers. I could use more help from other devs. You have been very helpful @Jay I understand how Realm works now but we both are unable to solve this Threading error apparently.
很抱歉我尝试了两种方法,我的领域配置和您的领域配置都在同一行中停止了我的代码。我想这一定是将其他领域对象存储在一个领域对象中的问题。这个数据库对我不起作用,我正在复制错误,显示我的代码,Realm开发人员没有积极支持。我可以从其他开发人员那里得到更多帮助。你帮了我很大的忙@Jay,我理解Realm现在是如何工作的,但我们显然都无法解决这个线程错误。
@DMarMon You must have some other issue involved and there is no threading in the answer in my code so it would not be possible to have a threading error. The code I posted in my answer is straight from a fully working project, which I use on three different Macs. Possibly corrupted data, bad OS, malware or something else unrelated to the code. Why don't you create a brand new project, add Realm SDK and then copy and paste my code. Should only take about 10 minutes and that will establish a baseline as if it doesn't work, you have other issues causing the problem.
@DMarMon您一定有其他问题,并且我的代码中的答案中没有线程,因此不可能出现线程错误。我在回答中发布的代码直接来自一个完整的工作项目,我在三台不同的Mac电脑上使用它。可能是损坏的数据、糟糕的操作系统、恶意软件或其他与代码无关的东西。你为什么不创建一个全新的项目,添加Realm SDK,然后复制并粘贴我的代码呢。应该只需要大约10分钟,这将建立一个基线,就好像它不起作用一样,你有其他问题导致了问题。
I wanted to express my sincere gratitude for all the help you provided me. Your support was truly valuable, and I deeply appreciate the time and effort you put into trying to assist me. However, after giving it a try and exploring different options, I've decided to opt for SQLite3 as it proved to be much easier for me to understand. Although I'm discarding Realm this time, I will consider it again in the future. Your advice and guidance will be of great value if I decide to revisit Realm. Thank you again for your kindness and willingness to help. I hope you have a fantastic day!
我想对你为我提供的所有帮助表示衷心的感谢。你的支持真的很有价值,我非常感谢你为帮助我付出的时间和精力。然而,在尝试了一下并探索了不同的选择后,我决定选择SQLite3,因为它对我来说更容易理解。虽然我这次放弃了境界,但我以后会再考虑的。如果我决定重游王国,你的建议和指导将非常有价值。再次感谢你的好意和乐于助人的精神。我希望你度过美好的一天!
我是一名优秀的程序员,十分优秀!