Realm.io deleting many objects takes too long - ios

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

Related

I want to thread data read from realm in iOS

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)

Swift - Realm , completion after successfully adding item

So i have this code that meant to add items into the realm:
static func insertAsynctTest(_ objects: [Object], success: #escaping () -> Void, failure: #escaping () -> Void) {
DispatchQueue.global().async {
autoreleasepool {
if let realm = getInstance() {
do {
try realm.write {
for object in objects {
realm.add(object, update: .modified)
}
success()
}
} catch let error as NSError {
print("Something went wrong: \(error.localizedDescription)")
failure()
}
}
failure()
}
}
}
The closure is a must because i need to know that the action is done.
What happens now is that i don't know if the realm finished adding in his thread, so the success() is a false because the loop finished but the adding isn't , and when i try to fetch the data after i am crushing with the follow error:"Realm accessed from incorrect thread".
Is there a way to know that the adding is done?
Thanks
Realm is not thread safe. "Realm accessed from incorrect thread" means you first initialized realm on a different thread and now you are trying to access realm on a different thread. You should always access realm on the thread that it is initialized first.
If you initialize realm in main thread first, you have to access realm only on main thread.
There is another approach to access realm across threads. It is by using ThreadSafeReference
//If you have a person initialized from a different thread, create a ThreadSafeReference for that object
let personRef = ThreadSafeReference(to: person)
Now you can use that object in any thread
DispatchQueue(label: "com.example.myApp.bg").async {
let realm = try! Realm()
guard let person = realm.resolve(personRef) else {
return // person was deleted
}
try! realm.write {
person.name = "Jane Doe"
}
}
Please refer realm documentation on thread safety.

Accessing realm and filter results in different threads

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

How to edit Codable data model while saving it's data

Hey I recently created released an app and I wanted to add some more features but the way that I saved the data of the app was in plists using Codable. The problem is that I want to add some more features and when I try to add or remove a variable in the data model it completely wipes the data. I really don't want my users to loose their data.
I have already tried making a new class that inherited the previous class, that stopped the data from being wiped but it didn't let me save anymore data. This is for an iOS app using the latest version of Swift and UIKit
my load data function
func loadClasses(){
if let data = try? Data(contentsOf: dataFilePath!){
let decoder = PropertyListDecoder()
do{
try classArray = decoder.decode([Course].self, from:
data)
}
catch{
print("error loading items \(error)")
}
}
if let data = try? Data(contentsOf: remindersDataFilePath!){
let decoder = PropertyListDecoder()
do{
try reminders = decoder.decode([Reminder].self, from:
data)
}
catch{
print("error loading items \(error)")
}
}
if let data = try? Data(contentsOf: completedDataFilePath!){
let decoder = PropertyListDecoder()
do{
try completedReminderes =
decoder.decode([Reminder].self, from: data)
}
catch{
print("error loading items \(error)")
}
}
if let data = try? Data(contentsOf: weightsDataFilePath!){
let decoder = PropertyListDecoder()
do{
try weights = decoder.decode(CourseWeights.self, from:
data)
print(weights.honors)
}
catch{
print("error loading items \(error)")
}
}
my save data function
func saveItems(){
let encoder = PropertyListEncoder()
do{
let data = try encoder.encode(classArray)
try data.write(to: dataFilePath!)
}catch{
print("Error encoding class array \(error)")
}
do{
let data = try encoder.encode(reminders)
try data.write(to: remindersDataFilePath!)
}catch{
print("Error encoding class array \(error)")
}
do{
let data = try encoder.encode(completedReminderes)
try data.write(to: completedDataFilePath!)
}catch{
print("Error encoding class array \(error)")
}
do{
let data = try encoder.encode(weights)
try data.write(to: weightsDataFilePath!)
}catch{
print("Error encoding weights array \(error)")
}
if(reminders.count>0){
for i in 0...reminders.count-1{
if(reminders.count > 0){
scheduleLocal(remind: reminders[i])
}
}
}
}
the data model I want to add more to
class oldReminder : Codable{
var name : String = "Untitled"
var completed : Bool = false
var willNotify : Bool = false
var due = Date()
var reminder = Date()
var course = Course()
let uuid = UUID().uuidString
}

How to know whether a Realm object was successfully updated?

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

Resources