Skip to content

Instantly share code, notes, and snippets.

@verebes1
Last active March 6, 2024 19:47
Show Gist options
  • Save verebes1/02950e46fff91456f2ad359b3f3ec3d9 to your computer and use it in GitHub Desktop.
Save verebes1/02950e46fff91456f2ad359b3f3ec3d9 to your computer and use it in GitHub Desktop.
Realm Cascade Deletion in Swift
import RealmSwift
import Realm
protocol CascadeDeleting {
func delete<S: Sequence>(_ objects: S, cascading: Bool) where S.Iterator.Element: Object
func delete<Entity: Object>(_ entity: Entity, cascading: Bool)
}
extension Realm: CascadeDeleting {
func delete<S: Sequence>(_ objects: S, cascading: Bool) where S.Iterator.Element: Object {
for obj in objects {
delete(obj, cascading: cascading)
}
}
func delete<Entity: Object>(_ entity: Entity, cascading: Bool) {
if cascading {
cascadeDelete(entity)
} else {
delete(entity)
}
}
}
private extension Realm {
private func cascadeDelete(_ entity: RLMObjectBase) {
guard let entity = entity as? Object else { return }
var toBeDeleted = Set<RLMObjectBase>()
toBeDeleted.insert(entity)
while !toBeDeleted.isEmpty {
guard let element = toBeDeleted.removeFirst() as? Object,
!element.isInvalidated else { continue }
resolve(element: element, toBeDeleted: &toBeDeleted)
}
}
private func resolve(element: Object, toBeDeleted: inout Set<RLMObjectBase>) {
element.objectSchema.properties.forEach {
guard let value = element.value(forKey: $0.name) else { return }
if let entity = value as? RLMObjectBase {
toBeDeleted.insert(entity)
} else if let list = value as? RLMSwiftCollectionBase {
for index in 0..<list._rlmCollection.count {
if let entity = list._rlmCollection.object(at: index) as? RLMObjectBase {
toBeDeleted.insert(entity)
}
}
}
}
delete(element)
}
}
@aleyooop
Copy link

aleyooop commented Jan 25, 2022

@jhoanarango @niralishaha25 as mentioned before, you can use Embedded Objects for automated cascade deleting. But if you still want to use the snippet on realm v10+, that should work as follows:

private func resolve(element: Object, toBeDeleted: inout Set<RLMObjectBase>) {
    element.objectSchema.properties.forEach {
        guard let value = element.value(forKey: $0.name) else { return }
        if let entity = value as? RLMObjectBase {
            toBeDeleted.insert(entity)
        } else if let list = value as? RLMSwiftCollectionBase {
            for index in 0..<list._rlmCollection.count {
                if let entity = list._rlmCollection.object(at: index) as? RLMObjectBase {
                    toBeDeleted.insert(entity)
                }
            }
        }
    }
    delete(element)
}

@verebes1
Copy link
Author

@aleyooop Thanks for your input. I've updated the Gist with your suggestion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment