簡體   English   中英

如何從 SwiftUI 列表和 Realm 中刪除數據

[英]How to delete data from SwiftUI List and Realm

以下代碼正確顯示 SwiftUI ListRealm數據庫中的所有“用戶”。 我的問題是滑動一行時刪除記錄。

當我滑動一行並點擊刪除按鈕時,我立即收到一個uncaught exception錯誤, List沒有更新,但我知道正確的項目已從Realm數據庫中刪除,因為下次我運行應用程序時,所選記錄不會出現。

這是我的代碼。

SwiftUI 代碼

import RealmSwift

struct ContentView: View {

    @State private var allUsers: Results<User> = realm.objects(User.self)

    var body: some View {
        VStack{
            Text("Second Tab")
            List{
                ForEach(allUsers, id:\.self) { user in
                    HStack{
                        Text(user.name)
                        Text("\(user.age)")
                    }
                }.onDelete(perform: deleteRow)
            }
        }
    }

    private func deleteRow(with indexSet: IndexSet){
        indexSet.forEach ({ index in
            try! realm.write {
                realm.delete(self.allUsers[index])
            }
        })
    }
}

Realm Model

import RealmSwift

class User:Object{
    @objc dynamic var name:String = ""
    @objc dynamic var age:Int = 0
    @objc dynamic var createdAt = NSDate()

    @objc dynamic var userID = UUID().uuidString
    override static func primaryKey() -> String? {
        return "userID"
    }
}

錯誤

由於未捕獲的異常“RLMException”而終止應用程序,原因:“索引 4 超出范圍(必須小於 4)。”

當然,這4項更改取決於Realm數據庫中有多少項目,在這種情況下,當我滑動並點擊刪除按鈕時,我有 5 條記錄。

我的期望是每次allUsers @State 變量更改時List都會更新,我知道我的問題不是完全理解綁定是如何工作的。

我究竟做錯了什么?

我的期望是每次 allUsers @State 變量更改時列表都會更新

這是正確的,但 state 沒有改變......以下應該工作

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 值

@State private var allUsers: Results<User> = realm.objects(User.self)

這是使用 Realm 時非常常見的錯誤。 它也發生在“傳統”視圖控制器中。

我發現的唯一可靠的解決方案,它顯着提高了應用程序的穩定性,是始終使用界面項而不是 realm object。

此外,在現實生活中,我們需要做一些處理,從服務器加載頭像圖像,添加一些復選框、選擇或其他任何東西,而且我們通常不需要顯示對象的所有屬性。 不知何故,這是一種 MVVM 方法。

順便說一句,你可以在循環之前調用realm.write ,不確定,但我認為最好減少上下文切換。

使用這種技術,無論是使用 SwiftUI 還是 UIViewControllers,都可以解決 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()
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM