Reading data from ios to realm and using threads at the same time
But "Realm accessed from incorrect thread." An error occurs
Is there a problem with your code?
let realm = try! Realm()
let readData = realm.objects(DataRealm.self)
for i in 0...readData.count-1 {
DispatchQueue.global().async {
self.parsing()
}
}
You cannot use Realm objects across threads. That's why you get this error.
But you can use references which you can pass across them.
I am not sure how to apply it to your code since there is no part where you use the individual objects from readData. But what you are searching for might be something like this:
let realm = try! Realm()
let readData = realm.objects(DataRealm.self)
for data in readData {
let readDataRef = ThreadSafeReference(to: data)
DispatchQueue.global().async {
self.parsing(readDataReference: readDataRef)
}
}
In your parsing() method you would need to get the object from the reference then:
let data = realm.resolve(readDataReference)
Related
Hello everyone!
I've run into a big problem. I'm trying to access the realm data in main thread but also since I need to do a lot of synchronizing operations with the data such as update, insert etc I decided to search if there is a possibility to do all of these operations asynchronously but I'm getting different errors for every method that I'm trying to implement.
I'm creating the realm database as follows:
realm = try Realm(configuration: Realm.Configuration(
fileURL: fileURL,
encryptionKey: nil,
schemaVersion: schemaVersion,
objectTypes: objectTypes))
Accessing data as follows:
guard let realm = realm else {
return nil
}
let results = realm.objects(SPUserModel.self)
return Array(results)
Doing all of these upsert operations in the mainthread will raise my memory up to 1GB which is bad. Making them asynchronously may be a solution but there are different threads and that's an issue.
Would be glad if you can help me with this.
extension Realm {
class func realmInstance() -> Realm? {
let realm = try Realm(configuration: Realm.Configuration(
fileURL: fileURL,
encryptionKey: nil,
schemaVersion: schemaVersion,
objectTypes: objectTypes))
return realm
}
access :
DispatchQueue(label: "background").async {
Realm.realmInstance()?.objects(SPUserModel.self)
}
I'm reading Delete/Reset all entries in Core Data?.
If I follow the steps below, I get an unexpected result:
Call the code below
Then query an entity in the simulator, I will get an entity back!!!
If I call clearCoreDataStore again (or do a restart), only then the value won't be retrieved from core-data
What am I missing?
func clearCoreDataStore() {
let entities = dataManager.persistentContainer.managedObjectModel.entities
for entity in entities {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity.name!)
let deleteReqest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try context.execute(deleteReqest)
} catch {
print(error)
}
}
dataManager.saveContext()
}
The objects being deleted from the persistent store are probably also in an in-memory object context. If so, that memory context must first be updated to reflect the deletions. A thorough discussion can be found here.
In a nutshell...
deleteRequest.resultType = NSBatchDeleteRequestResultType.resultTypeObjectIDs
let result = try context.execute(deleteRequest) as? NSBatchDeleteResult
let objectIDArray = result?.result as? [NSManagedObjectID]
let changes = [NSDeletedObjectsKey : objectIDArray]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [context])
I am late to this party and newbie to Realm
I have created a signleton class having following method to write but it crashes at times because incorrect thread access
Let me know what I am doing wrong here.
func save<T:Object>(_ realmObject:T) {
let backgroundQueue = DispatchQueue(label: ".realm", qos: .background)
backgroundQueue.async {
let realm = try! Realm()
try! realm.write {
realm.add(realmObject)
}
}
}
Thanks for asking this question! The incorrect thread access exception is a result of the Realm object being passed through a thread boundary. I recommend reading the documentation on Passing Instances Across Threads and this blog post (specifically the section on thread confinement).
In order to avoid that exception, you'll need to change your code to:
func save<T:Object>(_ realmObject:T) {
let realmObjectRef = ThreadSafeReference(to: realmObject)
let backgroundQueue = DispatchQueue(label: ".realm", qos: .background)
backgroundQueue.async {
guard let realmObject = realm.resolve(realmObjectRef) else {
return // although proper error handling should happen
}
let realm = try! Realm()
try! realm.write {
realm.add(realmObject)
}
}
}
The ThreadSafeReference object, documented here provides you with a thread safe reference for a given Realm object that can be passed through a thread boundary and then resolved back to a thread-confined object once you're safely inside a different thread. I hope this helps and let me know if you need anything else. Cheers!
I am using Realm mobile database. I update Realm objects using the following code. I want to get a callback with whether or not that Realm object was successfully updated.
do {
let realm = try Realm()
realm.beginWrite()
if let Settings = realm.objects(ModelClass).first {
Settings.settingsVal = settingsValue
realm.add(Settings, update: true)
}
try realm.commitWrite()
}
catch {
}
There are a number of different ways to achieve what you are looking to do, including using closures/delegates to provide a callback mechanism, however the simplest way to know that the update was successful would be to add code inside the try block:
do {
let realm = try Realm()
realm.beginWrite()
if let Settings = realm.objects(ModelClass).first {
Settings.settingsVal = settingsValue
realm.add(Settings, update: true)
}
try realm.commitWrite()
print("Success")
}
catch{
}
}
I have stored some chat data in realm, where I added > 40k objects for performance tests. The querying is fast, but the deleting takes too long and freezes the UI:
static func deleteMessagesForChatId(chatId: String) {
dispatch_async(dispatch_queue_create("background", nil)) {
let realm = try! Realm()
let realmChatMessages = realm.objects(RealmChatMessage).filter("chatId = '\(chatId)'")
try! realm.write {
realm.delete(realmChatMessages)
print("message deleted from realm")
}
}
}
Instead of try! realm.write try using:
realm.beginWrite()
realm.delete(realmChatMessages)
try! realm.commitWrite()