मैं Realm Swift टीम द्वारा प्रदान किए गए ListSwiftUI उदाहरण का अनुसरण करने का प्रयास कर रहा हूं। यह मेरे लिए बहुत अच्छा काम कर रहा है, लेकिन जब मैं एक RealmSwift.List<Object> से हटाने की कोशिश करता हूं तो मुझे एक समस्या का सामना करना पड़ता है, ऐप एक अपवाद के साथ क्रैश हो जाता है "Terminating app due to uncaught exception 'RLMException', reason: 'Index 5 is out of bounds (must be less than 5).'"

आदर्श:

final class Todo: Object, ObjectKeyIdentifiable {
    @objc dynamic var id: String = UUID().uuidString
    @objc dynamic var name: String = ""
    @objc dynamic var createdAt: Date = Date()
    
    override class func primaryKey() -> String? {
        "id"
    }
}

final class Todos: Object {
    @objc dynamic var id: Int = 0
    
    let todos = List<Todo>()
    
    override class func primaryKey() -> String? {
        "id"
    }
}

दृश्य प्रतिनिधि। स्विफ्ट

let realm = try! Realm()
var todos = realm.object(ofType: Todos.self, forPrimaryKey: 0)
if todos == nil {
    todos = try! realm.write { realm.create(Todos.self, value: []) }
}

// Create the SwiftUI view that provides the window contents.
let contentView = ContentView(todos: todos!.todos)

सामग्री दृश्य.स्विफ्ट

@ObservedObject var todos: RealmSwift.List<Todo>
var body: some View {
    ForEach(todos) { (todo: Todo) in
        Text("\(todo.name)")
        .onDelete(perform: delete)
}

func delete(at offsets: IndexSet) {
    if let realm = todos.realm {
        try! realm.write {
            realm.delete(todos[offsets.first!])
        }
    } else {
        todos.remove(at: offsets.first!)
    }
}

मैंने रीयलम स्टूडियो में अपनी टोडोस सूची और डीबी की गिनती की जांच की है, इसमें वास्तव में इंडेक्स 5 है। और यह क्रैश केवल इंडेक्स 5 के लिए विशिष्ट नहीं है, उदा। अगर मेरे पास सूची में केवल 2 आइटम हैं, तो ऐप Index 1 के साथ क्रैश हो जाता है या जब इसमें 5 आइटम होते हैं, तो यह Index 4 के साथ क्रैश हो जाता है।

उदाहरण में काफी समान डेटा मॉडल हैं और यह पूरी तरह से काम करता है। तो मैं यहाँ क्या गलत कर रहा हूँ?

0
m.umar 9 सितंबर 2020, 23:04

1 उत्तर

सबसे बढ़िया उत्तर

मुद्दा यह है कि आपकी todos सूची से एक todo को हटाने से स्विफ्टुई ViewGraph में बदलाव को फिर से बनाने में असमर्थ है क्योंकि रिकॉर्ड स्पष्ट रूप से अब नहीं है। पहले रिकॉर्ड को हटाकर और फिर इसे अपनी todos सूची से हटाकर, स्विफ्टुई @ObservedObject संपत्ति में परिवर्तन के कारण दृश्य को फिर से प्रस्तुत करता है। निम्नलिखित का प्रयास करें:

  1. अपने दायरे के संस्करण को नवीनतम संस्करण में अपडेट करने का प्रयास करें। वर्तमान में 5.4.0 पर। उन्होंने कंबाइन/स्विफ्टयूआई के लिए समर्थन जोड़ा है। देखें: https://realm.io/docs/swift/latest/ api/Enums/Publishers.html प्रकाशकों की सूची के लिए। नवीनतम संस्करण का उपयोग करके आपके पास निम्नलिखित प्रकाशकों का उपयोग करने की संभावना है:

    • objectWillChange - हर बार संग्रह या वस्तु के बदलने पर शून्य प्रकाशित होता है
    • publisher - संग्रह के हर बार बदलने पर उसे प्रकाशित करता है
    • changesetPublisher - हर बार संग्रह में परिवर्तन होने पर एक RealmCollectionChangeset प्रकाशित करता है या यदि किसी दायरे वस्तु पर उपयोग किया जाता है तो वह उस वस्तु के परिवर्तनों को प्रकाशित करता है
    • objectWillChange - हर बार वस्तु बदलने पर शून्य प्रकाशित करता है
    • freeze() - संग्रह या वस्तु को जमा देता है और इसे अपरिवर्तनीय बनाता है।
  2. freeze() अपने todos संग्रह को ForEach(todos.freeze()) का उपयोग करके। संग्रह को फ्रीज करके स्विफ्टयूआई "रेंडरिंग" चेक करने में सक्षम है।

एक और तरीका यह होगा कि सूचीबद्ध प्रकाशकों की सदस्यता लें और उनके परिवर्तनों के अनुसार प्रतिक्रिया दें।

2
Erwin Schens 10 सितंबर 2020, 09:11