Skip to content

Instantly share code, notes, and snippets.

@georgescumihai
Created August 26, 2020 16:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save georgescumihai/5c7e93322c59e6808c671bc65beaa221 to your computer and use it in GitHub Desktop.
Save georgescumihai/5c7e93322c59e6808c671bc65beaa221 to your computer and use it in GitHub Desktop.
Cascade deletion for realm.
// This solution is an adaption of from https://gist.github.com/verebes1/02950e46fff91456f2ad359b3f3ec3d9
// It is for Objective-C
// With the fix for objects with same hash.
import Foundation
import Realm
/// Cascade deletion for realm.
public extension RLMRealm {
/// Delete a realm object and his child objects.
/// - Parameter object: object to be deleted.
/// - Parameter cascade: true if the deletion should remove the child objects, otherwise false.
@objc func deleteObject(_ object: RLMObject, cascade: Bool) {
guard cascade else {
delete(object)
return
}
cascadeDelete([object])
}
/// Cascade delete a realm objects array.
/// - Parameter objects: array with objects to be deleted.
/// - Parameter cascade: true if the deletion should remove the child objects, otherwise false.
func deleteObjects(_ objects: [RLMObject], cascade: Bool) {
guard cascade else {
objects.forEach(delete(_:))
return
}
cascadeDelete(objects)
}
/// Cascade delete a realm collection.
/// - Parameter objects: enumeration with objects to be deleted.
/// - Parameter cascade: true if the deletion should remove the child objects, otherwise false.
@objc func deleteObjects(_ objects: NSFastEnumeration, cascade: Bool) {
// If cascade is false, then do a normal delete.
guard cascade else {
deleteObjects(objects)
return
}
var iterator = NSFastEnumerationIterator(objects)
while let element = iterator.next() {
guard let object = element as? RLMObject else {
continue
}
cascadeDelete([object])
}
}
private func cascadeDelete(_ objects: [RLMObject]) {
var toBeDeleted = objects
while let element = toBeDeleted.popLast() {
guard !element.isInvalidated, element.realm != nil else { continue }
resolve(element: element, toBeDeleted: &toBeDeleted)
delete(element)
}
}
private func resolve(element: RLMObject, toBeDeleted: inout [RLMObject]) {
func foundChild(entity: RLMObject) {
toBeDeleted.append(entity)
}
func foundChild(collection: RLMCollection) {
(0..<collection.count)
.map(collection.object(at:))
.compactMap { $0 as? RLMObject }
.forEach(foundChild)
}
element
.objectSchema
.properties
.map(\.name)
.compactMap(element.value(forKey:))
.forEach { value in
if let entity = value as? RLMObject {
foundChild(entity: entity)
} else if let collection = value as? RLMCollection {
foundChild(collection: collection)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment