- 
      
 - 
        
Save krodak/b47ea81b3ae25ca2f10c27476bed450c to your computer and use it in GitHub Desktop.  
| import RealmSwift | |
| import Realm | |
| protocol CascadeDeleting: class { | |
| func delete<Entity>(_ list: List<Entity>, cascading: Bool) | |
| func delete<Entity>(_ results: Results<Entity>, cascading: Bool) | |
| func delete<Entity: Object>(_ entity: Entity, cascading: Bool) | |
| } | |
| extension Realm: CascadeDeleting { | |
| func delete<Entity>(_ list: List<Entity>, cascading: Bool) { | |
| list.forEach { | |
| delete($0, cascading: cascading) | |
| } | |
| } | |
| func delete<Entity>(_ results: Results<Entity>, cascading: Bool) { | |
| results.forEach { | |
| delete($0, 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? RealmSwift.ListBase { | |
| for index in 0..<list._rlmArray.count { | |
| toBeDeleted.insert(list._rlmArray.object(at: index)) | |
| } | |
| } | |
| } | |
| delete(element) | |
| } | |
| } | 
Fixed for Realm 4 and removed the need to specify types for the properties as long as all objects have a primaryKey().
https://gist.github.com/samrayner/44d34fdc77e7d8d766fd467d557753a9
Hello,
Since Realm 10.8.0, RealmSwift.ListBase or RLMListBase are not reachable anymore. Does anyone have an idea how to replace them ?
Thank you very much for your help.
I think the following code should be used, but I am yet to see it in production
internal protocol CascadingDeletable: RealmSwift.Object {
	static var propertiesToCascadeDelete: [String] { get }
}
extension Realm {
	internal func cascadingDelete(_ object: RealmSwift.Object) {
		var toBeDeleted: Set<RLMObjectBase> = [object]
		while let element = toBeDeleted.popFirst() as? RealmSwift.Object {
			guard !element.isInvalidated else { continue }
			if let cascadingDeletable = element as? CascadingDeletable {
				cascade(into: cascadingDeletable, toBeDeleted: &toBeDeleted)
			}
			delete(element)
		}
	}
	private func cascade(into object: CascadingDeletable, toBeDeleted: inout Set<RLMObjectBase>) {
		let objectType = type(of: object)
		guard let schema = objectType.sharedSchema() else { return }
		let primaryKey = objectType.primaryKey()
		let primaryKeyValue = primaryKey.flatMap(object.value(forKey:))
		let properties = (schema.properties + schema.computedProperties)
			.filter { objectType.propertiesToCascadeDelete.contains($0.name) }
		for property in properties {
			switch object.value(forKey: property.name) {
			case let realmObject as RLMObjectBase:
				toBeDeleted.insert(realmObject)
			case let list as RLMSwiftCollectionBase:
				for index in 0 ..< list._rlmCollection.count {
					guard let realmObject = list._rlmCollection.object(at: index) as? RLMObjectBase else { continue }
					toBeDeleted.insert(realmObject)
				}
			default: // LinkingObjects
				if let linkOriginPropertyName = property.linkOriginPropertyName,
				   let linkOriginTypeName = property.objectClassName,
				   let primaryKey = primaryKey,
				   let primaryKeyValue = primaryKeyValue {
					dynamicObjects(linkOriginTypeName)
						.filter("%K == %@", "\(linkOriginPropertyName).\(primaryKey)", primaryKeyValue)
						.forEach { toBeDeleted.insert($0) }
				}
			}
		}
	}
}
    Updated code to use RLMSwiftCollectionBase instead of RealmSwift.ListBase which looks fine at first glance but using this hack with latest release seems pretty dangerous, since Realm 10.0 theres a built in cascade delete https://www.mongodb.com/developer/article/realm-database-cascading-deletes/#cascading-deletes probably better to stick with it although I didn't tried that yet.
extension Realm {
    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 object = list._rlmCollection.object(at: index) as? RLMObjectBase {
                        toBeDeleted.insert(object)
                    }
                }
            }
        }
        
        delete(element)
    }
}
    @cpd, thanks for letting us know! I didn't know the cascading delete was implemented. Thanks!
@cpd, Thanks a lot mate!
I was having trouble with Resolve function as RealmSwift.ListBase is no longer supported in RealmSwift v10.17.0.
Your code with RLMSwiftCollectionBase helped me, Thanks again.
LinkingObjectsBasenot found in Realm 4.x.x