【问题标题】:Error deleting records from a SwiftUI List and Realm从 SwiftUI 列表和领域中删除记录时出错
【发布时间】:2020-04-16 12:22:12
【问题描述】:

有没有人能够成功地将RealmSwiftUI 集成在一起,尤其是从SwiftUI List 中删除记录/行?我尝试了几种不同的方法,但无论我做什么,我都会得到同样的错误。在阅读了一些相关主题后,我发现其他人也有同样的问题。

以下代码成功地在 SwiftUI List 中显示来自 Realm 的所有项目,我可以创建新项目,它们按预期显示在列表中,我的问题是当我尝试从列表中删除记录时手动按下按钮或向左滑动删除所选行,我得到一个 Index is out of bounds 错误。

知道是什么导致了错误吗?

这是我的代码:

领域模型

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

SwiftUI 代码

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 条记录。

仅供参考 - 错误指向带有 Thread 1: signal SIGABRT 的 AppDelegate 文件。

【问题讨论】:

    标签: ios swift realm swiftui swiftui-list


    【解决方案1】:

    这是我如何执行此操作的示例。这没有领域操作,但我希望你明白你可以把领域的东西放在哪里。 (我也几乎从不直接使用领域对象,而是将它们转换为结构或类。)

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

    【讨论】:

    • 我非常感谢您的努力,但我认为我的主要问题在于 Realm 的工作方式,但我会尝试一下。那么,您是否能够让 Realm 与 SiwftUI 一起工作?
    • 是的,我在我的一个应用程序中这样做,但我通过 RealmObserverModel() 模型使用这种间接方式,所以我可以确定我得到了正确的结果。将领域结果直接绑定到 Bindable 或 Observable 可能是关键的 imo、异步问题、尝试 catch ...等。我在应用程序中使用它:apps.apple.com/us/app/arvie-ar-video-walls/id1489863285 当您保存 ar 工作室时......
    • 对于如何将 Realm 对象合并到您的代码中,我仍然有点困惑,但我会试一试,让您知道它是如何进行的。顺便说一句,恭喜,非常酷的应用程序。谢谢。
    • 我会调用 realmService 来更新 func getDogs() 中的 Published var .... 我还将领域对象转换为普通的结构或类,在 SwiftUI 中更易于使用,代码更多让你转变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    相关资源
    最近更新 更多