从 SwiftUI 列表和领域中删除记录时出错

Posted

技术标签:

【中文标题】从 SwiftUI 列表和领域中删除记录时出错【英文标题】:Error deleting records from a SwiftUI List and Realm 【发布时间】: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 文件。

【问题讨论】:

【参考方案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 中更易于使用,代码更多让你转变。

以上是关于从 SwiftUI 列表和领域中删除记录时出错的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式从 SwiftUI 列表中删除行并刷新列表视图?

从 SwiftUI 中的列表中删除绑定

点击 SwiftUI 时从列表中删除

从 SwiftUI 的列表中删除列表元素

从 SwiftUI 的列表中删除列表元素

在 SwiftUI 中使用模态视图删除列表中的项目时崩溃