从 SwiftUI 列表和领域中删除记录时出错
Posted
技术标签:
【中文标题】从 SwiftUI 列表和领域中删除记录时出错【英文标题】:Error deleting records from a SwiftUI List and Realm 【发布时间】:2020-04-16 12:22:12 【问题描述】:有没有人能够成功地将Realm
与SwiftUI
集成在一起,尤其是从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 列表和领域中删除记录时出错的主要内容,如果未能解决你的问题,请参考以下文章