Pass the following method to perform with .onDelete of List of SwiftUI,
func deleteRow(offsets: IndexSet) {
guard let index = offsets.first else {
return
}
let deleteItem = hoges[index]
try! realm.write {
realm.delete(deleteItem)
}
self.hoges = realm.objects(Hoge.self)
}
As a test, when I wrote it like this, it crashed with the error "Index ~ is out of bounds (must be less than ~)."
https://stackoverflow.com/questions/61165998/how-to-delete-data-from-swiftui-list-and-realm
~~ If you refer to here and turn the index with forEach, it will not crash! ~~
func deleteRow(offsets: IndexSet) {
offsets.forEach({ index in
try! realm.write {
realm.delete(self.hoges[index])
}
})
self.hoges = realm.objects(Hoge.self)
}
Postscript: I thought that it was fixed by the above, but it only stopped crashing when the last data was deleted, and it crashed as well when I deleted other cells. I customized forEach by referring to the information that came out by google, and I made an exist method to check if the data exists, but none of them worked,
Temporarily referring to this article, create a Model that defines the same value as the Realm data defined by @objc dynamic var
with a struct, substitute it from Realm with the initializer of ViewModel, and directly from List Realm I avoided the crash by taking the value from the Model without referring to.
import RealmSwift
class Hoge: Object, Identifiable {
@objc dynamic var id: String = ""
@objc dynamic var title: String = ""
override static func primaryKey() -> String? {
return "id"
}
}
struct HogeModel {
let id: String
let title: String
}
https://llcc.hatenablog.com/entry/2020/04/26/205254
This method may be quite troublesome if the development scale is large.
There seems to be a similar issue for RealmSwift, but I hope it will be even easier to use with SwiftUI! https://github.com/realm/realm-cocoa/issues/6635
While searching for further improvements, I found out that there are Frozen Objects that can handle Realm Results immutable. https://realm.io/blog/realm-database-a-new-architecture-and-frozen-objects/
I haven't figured out how to use it in detail yet, but I found an easier way than recreating the Model.
self.hoges = realm.objects(Hoge.self)?.freeze()
I really want to write it like this, but if I declare it like this and perform an operation that uses realm.write such as delete, it will crash.
So, tentatively, when you set the immutable property to Published and write it with the initializer or realm.write, you can avoid the crash by assigning it!
HogeViewModel.swift
var hoges: Results<Hoge>?
@Published var freezedHoges: Results<Hoge>?
let realm = try! Realm()
init() {
hoges = realm.objects(Hoge.self)
freezedHoges = hoges?.freeze()
}
func addHoge() {
let hoge = Hoge()
hoge.id = NSUUID().uuidString
hoge.title = "fuga"
try! realm.write {
realm.add(hoge)
}
freezedHoges = hoges?.freeze()
}
Recommended Posts