شرح Cascading Deletes بإستخدام Realm

اكثر شغلة مزعجة في Realm انها ماتدعم Cascading Deletes

بمعنى اذا عندك Database فيها Parent و Child لما تحذف الـ Parent المفروض يحذف الـ Child معاه

هذا الامر في اغلب الـ Database الا Realm

مثال للمشكلة بإستخدام Realm ، عندي هذا الـ Model

عباره عن جدول Contact وبداخله جدول Address

حسب الي ذكرته سابقا في ميزة الـ Cascading Deletes

البديهي اذا حذفت Contact المفروض يحذف الـ Address

لكن في Realm ماراح يصير هذا الشي!

class Contact: Object {
    @objc dynamic var _id = ObjectId.generate()
    @objc dynamic var name = ""

    @objc dynamic var address: Address?

    override static func primaryKey() -> String? {
       return "_id"
    }

    override init() {
        super.init()
    }
    
    convenience init(name: String, address: Address) {
       self.init()
       self.name = name
       self.address = address
      }
    }

class Address: Object {
    @objc dynamic var country: String? 
    @objc dynamic var city: String?

    override init() {
        super.init()
    }
    
    init(country: String? = nil, city: String? = nil) {
        self.country = country
        self.city = city
    }
}

مثال اضفت contact و address
وبعدها حذفت الـ contact
النتيجة انحذف الـ Contact لكن الـ Address لازال متوفر !

struct ContentView: View {
    let realm = try! Realm()
    
    var body: some View {
        VStack {
            Text("Demo")
            
            Button {
                let contact = Contact()
                
                let newContact = Contact(name: "Ahmad", address: Address(country: "Saudi Arabia", city: "Jeddah"))
                
                
                try! realm.write {
                    realm.add(newContact)
                }
                
                
            } label: {
                Text("Add")
            }
            
            
            Button {
                let ahmadContact = realm.objects(Contact.self)
                
                guard let ahmadContact = realm.objects(Contact.self)
                    .filter("address.city = %@", "Jeddah")
                    .first,
                      let ahmadContactAddress = ahmadContact.address else {
                    print("Could not find Ahmad address!")
                    return
                }
                
                
                try! realm.write {
                    // Delete the instance from the realm.
                    realm.delete(ahmadContact)
                }
                
            } label: {
                Text("Delete")
            }
            
            
        }
        .padding()
    }
}

في النسخ السابقة لحل هذه المشكلة
يتوجب عليك حذف جميع الـ Child وبعدها تحذف الـ Parent

  Button {
                // delete child then delete parent
                if let contactToDelete = realm.objects (Contact.self).filter("name = 'Ahmad'").first {
                    try! realm.write {
                        if let addressToDelete = contactToDelete.address {
                            realm.delete(addressToDelete)
                        }
                        realm.delete (contactToDelete)
                    }
                }
                
            } label: {
                Text("Delete")
            }

النتيجة انحذف الـ Child و الـ Parent

في السابق كانت هذه الطريقة ولسنوات كانت مزعجة

لكن واخيرا في نسخة رقم 10 التي صدرت في بداية السنة الماضية 2022 Realm

صارات تدعم Cascading Deletes !
هذه الميزة من 2017 نطالب بإضافتها!

عموما الطريقة جدا بسيطة ومختصره وتحتاج خطوتين فقط

الخطوه الاولى : تحتاج تبدل الـ Object الى EmbeddedObject لكل الـ Child

الخطوة الثانية: لازم كل المتغيرات تكون نوعها Optional تحديث للـ Models

فالتغيير الوحيد هو تغير الـ Address من Object الى EmbeddedObject

class Address: EmbeddedObject {
    @objc dynamic var country: String? = nil
    @objc dynamic var city: String? = nil

    override init() {
        super.init()
    }
    
    init(country: String? = nil, city: String? = nil) {
        self.country = country
        self.city = city
    }
}

الان فقط احذف الـ Parent وراح ينحذف الـ Child معاه

بمعنى حذف Contact راح يحذف Address بدون ما تحتاج تعمل اي حاجة

ولاحظ شكل الجدول تغير address ماصار موجود في الجهة اليسرى وصار address مكتوب جنبه (Embedded)
تقدر تضغط عليه لفتح جدول الـ Address

معلومة إضافية ايضا في النسخة الـ 10 Realm
اصبحت ايضا تدعم نوع Decimal128 بمعنى تقدر تضيف متغير من نوع Float , CGFloat الخ .. ،
بدون ما تحتاج تحولهم الى Double وتفقد بعض الارقام