[有人能够成功地将Realm
与SwiftUI
集成,特别是从SwiftUI List
删除记录/行吗?我尝试了几种不同的方法,但是无论我做什么我都会遇到相同的错误。阅读一些相关的主题后,我发现其他人也有同样的问题。
以下代码成功地将Realm
中的所有项目显示在SwiftUI List
中,我可以创建新的项目,并且它们按预期显示在列表中,我的问题是当我尝试通过以下任一方法从列表中删除记录时手动按下按钮或向左滑动以删除所选行,我得到一个索引超出范围错误。
任何想法可能导致错误的原因吗?
这是我的代码:
class Dog: Object {
@objc dynamic var name = ""
@objc dynamic var age = 0
@objc dynamic var createdAt = NSDate()
@objc dynamic var userID = UUID().uuidString
override static func primaryKey() -> String? {
return "userID"
}
}
class BindableResults<Element>: ObservableObject where Element: RealmSwift.RealmCollectionValue {
var results: Results<Element>
private var token: NotificationToken!
init(results: Results<Element>) {
self.results = results
lateInit()
}
func lateInit() {
token = results.observe { [weak self] _ in
self?.objectWillChange.send()
}
}
deinit {
token.invalidate()
}
}
struct DogRow: View {
var dog = Dog()
var body: some View {
HStack {
Text(dog.name)
Text("\(dog.age)")
}
}
}
struct ContentView : View {
@ObservedObject var dogs = BindableResults(results: try! Realm().objects(Dog.self))
var body: some View {
VStack{
List{
ForEach(dogs.results, id: \.name) { dog in
DogRow(dog: dog)
}.onDelete(perform: deleteRow )
}
Button(action: {
try! realm.write {
realm.delete(self.dogs.results[0])
}
}){
Text("Delete User")
}
}
}
private func deleteRow(with indexSet: IndexSet){
indexSet.forEach ({ index in
try! realm.write {
realm.delete(self.dogs.results[index])
}
})
}
}
由于未捕获的异常“ RLMException”而终止应用程序,原因:“索引23超出范围(必须小于23)。”
当然,这23项更改取决于Realm数据库中的项目数,在这种情况下,当我轻按并点击删除按钮时,我有24条记录。
FYI-错误指向带有Thread 1: signal SIGABRT
的AppDelegate文件。
这里是我如何执行此操作的示例。这是没有领域操作的,但我希望您能将您可以放入领域的东西的想法。 (我也几乎从不直接使用领域对象,而是将它们转换为结构或类。)
import Foundation
import Realm
import Combine
import SwiftUI
struct dogs: Hashable {
let name: String
}
class RealmObserverModel: ObservableObject {
var didChange = PassthroughSubject<Void, Never>()
@Published var dogsList: [dogs] = [dogs(name: "Dog 1"), dogs(name: "Dog 2")]
// get your realm objects here and set it to
// the @Publsished var
func getDogs() {
let count = dogsList.count + 1
dogsList.append(dogs(name: "Dog \(count)"))
}
// get your realm objects here and set it to
// the @Publsished var
func deletetDogs() {
_ = dogsList.popLast()
}
}
/// Master View
struct DogView: View {
@EnvironmentObject var observer: RealmObserverModel
var body: some View {
VStack{
DogsListView(dogsList: $observer.dogsList)
HStack{
Button(action: {
self.observer.getDogs()
}) {
Text("Get more dogs")
}
Button(action: {
self.observer.deletetDogs()
}) {
Text("Delete dogs")
}
}
}
}
}
// List Subview wiht Binding
struct DogsListView: View {
@Binding var dogsList: [dogs]
var body: some View {
VStack{
List{
ForEach(dogsList, id:\.self) { dog in
Text("\(dog.name)")
}
}
}
}
}
struct DogView_Previews: PreviewProvider {
static var previews: some View {
DogView().environmentObject(RealmObserverModel())
}
}