Ios 如何从SwiftUI列表和域中删除数据
以下代码在SwiftUIIos 如何从SwiftUI列表和域中删除数据,ios,realm,swiftui,swiftui-list,Ios,Realm,Swiftui,Swiftui List,以下代码在SwiftUI列表中正确显示领域数据库中的所有“用户”。我的问题是在我刷行时删除记录 当我刷一行并点击删除按钮时,我立即得到一个未捕获异常错误,列表不会更新,但我知道正确的项目会从领域数据库中删除,因为我下次运行应用程序时,所选记录不会显示 这是我的密码 快捷代码 错误 由于未捕获异常“RLMEException”而终止应用程序,原因:“索引4超出范围(必须小于4)。” 当然,4的变化取决于领域数据库中的项目数量,在这种情况下,当我滑动并点击删除按钮时,我有5条记录 我的期望是,列表将
列表中正确显示领域
数据库中的所有“用户”。我的问题是在我刷行时删除记录
当我刷一行并点击删除按钮时,我立即得到一个未捕获异常
错误,列表
不会更新,但我知道正确的项目会从领域
数据库中删除,因为我下次运行应用程序时,所选记录不会显示
这是我的密码
快捷代码
错误
由于未捕获异常“RLMEException”而终止应用程序,原因:“索引4超出范围(必须小于4)。”
当然,4
的变化取决于领域
数据库中的项目数量,在这种情况下,当我滑动并点击删除按钮时,我有5条记录
我的期望是,列表
将在每次allUsers
@状态变量更改时更新,我知道我的问题是不能完全理解绑定是如何工作的
我做错了什么
我的期望是,该列表将在每次
allUsers@状态变量更改
这是正确的,但状态未更改。。。以下几点应该有效
private func deleteRow(with indexSet: IndexSet){
indexSet.forEach ({ index in
try! realm.write {
realm.delete(self.allUsers[index])
}
})
self.allUsers = realm.objects(User.self) // << refetch !!
}
private func deleteRow(带indexSet:indexSet){
index.forEach({index in
试试看!写吧{
realm.delete(self.alluser[index])
}
})
self.alluser=realm.objects(User.self)/这是处理realm时非常常见的错误。它也发生在“传统”视图控制器中
我发现的唯一一个解决方案是始终使用接口项而不是领域对象,这大大提高了应用程序的稳定性
此外,在现实生活中,我们需要做一些处理,从服务器加载化身图像,添加一些复选框、选择或其他什么,我们通常不需要显示对象的所有属性。不知何故,这是一种MVVM方法
顺便说一下,您可以调用领域。在循环之前编写,不确定,但我认为最好尽量减少上下文切换
使用此技术,无论是使用SwiftUI还是UIViewController,都将永远解决RLM崩溃问题
struct ContentView: View {
struct UserItem: Hashable {
var id: String
var name: String
var age: Int
}
private var allUsers: Results<User> = realm.objects(User.self)
@State private var userItems: [UserItem] = []
func updateItems() {
userItems = allUsers.map {
UserItem(id: $0.userID, name: $0.name, age: $0.age)
}
}
var body: some View {
VStack {
Text("Second Tab")
List{
ForEach(userItems, id:\.self) { user in
HStack{
Text(user.name)
Text("\(user.age)")
}
}
.onDelete(perform: deleteRow)
}
}.onAppear() {
updateItems()
}
}
private func deleteRow(with indexSet: IndexSet){
try! realm.write {
indexSet.forEach {
realm.delete(self.allUsers[$0])
}
}
updateItems()
}
}
struct ContentView:View{
struct UserItem:Hashable{
变量id:String
变量名称:String
变量年龄:Int
}
私有变量alluser:Results=realm.objects(User.self)
@国家私有var userItems:[UserItem]=[]
func updateItems(){
userItems=allUsers.map{
UserItem(id:$0.userID,name:$0.name,age:$0.age)
}
}
var body:一些观点{
VStack{
文本(“第二个选项卡”)
名单{
ForEach(userItems,id:\.self){user in
HStack{
文本(用户名)
文本(“\(user.age)”)
}
}
.onDelete(执行:deleteRow)
}
}.onAppear(){
updateItems()
}
}
private func deleteRow(带indexSet:indexSet){
试试看!写吧{
索引集forEach{
realm.delete(self.alluser[$0])
}
}
updateItems()
}
}
不幸的是,按照您的建议从域中删除记录后重新获取不起作用,我得到了同样的错误。@fs\u tigre不幸的是由于结果对象的性质,分配初始状态值是不正确的。它们是实时更新的-这意味着域结果对象保持与其子对象的实时连接ng对象,如果一个对象被添加到领域,结果将包括该对象。如果一个对象被删除,该对象将不再包括在这些结果中。可以观察结果对象的更改,然后如果一个对象被添加、修改或删除,就可以采取行动。我很确定@State
在这里不是正确的事情。任何在哪里可以找到有关如何重构代码的信息?@fs_tigre有时更简单,因此我只需将allUsers结果设置为一个类变量,然后向该变量添加一个观察者。在观察者块中,当某些内容发生更改时,只需刷新tableView。如果tableView中不需要动画UI元素,就可以了。如果确实如此,然后您可以利用observer闭包在更细粒度的行级别控制tableView更新。@fs_tigre,我越想这一点,就越倾向于认为原因是其他地方……如果崩溃是由SwiftUI引起的,则可能是由iOS引起的……如UIKit内部异常或swift库。..但您声明它是RLMEException,这是领域内部异常,而根据提供的代码,由于在写事务中执行删除操作,所有内容都应该是正确的…并且结果应该立即按照设计和记录进行更新。您在哪一行的确切操作上获得此异常?错误指向AppDelegate-Th阅读1:signal SIGABRT
第一个问题是,在列表或ForEach中传递的数据必须符合可识别的协议。此外,由于结果对象的性质,Realm不太适合SwiftUI-您可能希望暂时依靠通知来处理UI更新。一旦Realm冻结了Objects,它将更容易实现领域功能。因此,如果我正确理解您的意思,您现在说的是,领域和SwiftUI不能很好地配合使用?了解领域端或SwiftUI上的通知?感谢您指出在列表或ForEach中传递的数据必须符合可识别协议的事实。这就是这是我们迄今为止的经验。这不是一个真正的领域“问题”,因为结果按预期工作——这是与SwiftUI性质的交互。这里有许多这样的问题,但没有实际的答案不是解决办法-
private func deleteRow(with indexSet: IndexSet){
indexSet.forEach ({ index in
try! realm.write {
realm.delete(self.allUsers[index])
}
})
self.allUsers = realm.objects(User.self) // << refetch !!
}
@State private var allUsers: Results<User> = realm.objects(User.self)
struct ContentView: View {
struct UserItem: Hashable {
var id: String
var name: String
var age: Int
}
private var allUsers: Results<User> = realm.objects(User.self)
@State private var userItems: [UserItem] = []
func updateItems() {
userItems = allUsers.map {
UserItem(id: $0.userID, name: $0.name, age: $0.age)
}
}
var body: some View {
VStack {
Text("Second Tab")
List{
ForEach(userItems, id:\.self) { user in
HStack{
Text(user.name)
Text("\(user.age)")
}
}
.onDelete(perform: deleteRow)
}
}.onAppear() {
updateItems()
}
}
private func deleteRow(with indexSet: IndexSet){
try! realm.write {
indexSet.forEach {
realm.delete(self.allUsers[$0])
}
}
updateItems()
}
}