Reputation: 11
I need to write a huge data(ex. 200000 input) to the realm, and I used realm.add() to write data in a background thread. But it got the crash message:
Terminating app due to uncaught exception 'RLMException', reason: 'Realm accessed from incorrect thread.'
let cities = try decoder.decode([City].self, from: dataFromStream)
let dispatchQueue = DispatchQueue(label: "com.example.myApp.bg", qos: .background)
dispatchQueue.async {
let myBackgroundRealm = try! Realm()
myBackgroundRealm.beginWrite()
for city in cities {
myBackgroundRealm.add(city, update: false)
}
try! myBackgroundRealm.commitWrite()
}
So I change to use Realm.create(), and it works. But I still don't understand what's the difference between Realm.create() and Realm.add() in writing a large data.
let cities = try decoder.decode([City].self, from: data)
let dispatchQueue = DispatchQueue(label: "com.example.myApp.bg", qos: .background)
dispatchQueue.async {
let myBackgroundRealm = try! Realm()
for city in cities {
try! myBackgroundRealm.write {
myBackgroundRealm.create(City.self, value: city, update: false)
}
}
}
Upvotes: 1
Views: 996
Reputation: 386
There shouldn't be any difference between adding with 'add' and 'create'. One thing that you also changed is a place where you open transaction (before the iteration over cities or each loop of the iteration). Each loop is the correct way, so other write transactions are not waiting for your large data to be inserted. The crash is still interesting, it appears background priority queue decided to allocate another thread in the middle of a transaction, causing the crash, which I thought should never happen.
Upvotes: 0
Reputation: 1534
When doing async writes to realm, you have to initialize a thread safe reference and resolve the reference in your background thread. Taken from realm's documentation https://realm.io/docs/swift/latest/#passing-instances-across-threads
let person = Person(name: "Jane")
try! realm.write {
realm.add(person)
}
let personRef = ThreadSafeReference(to: person)
DispatchQueue(label: "background").async {
autoreleasepool {
let realm = try! Realm()
guard let person = realm.resolve(personRef) else {
return // person was deleted
}
try! realm.write {
person.name = "Jane Doe"
}
}
}
Upvotes: 1