Search code examples
iosswiftcore-data

How can I clear the core data?


my app crashes sometimes randomly when I try to log out and clear the Core Data. When I debug cachedResults.forEach { coreDataContext.delete($0) }, the app crashes on this line. How can I fix this? Please see my code below and guide me on how to resolve this. Thanks!

func clearConversationList() {
        objc_sync_enter(self)
                defer { objc_sync_exit(self) }
                
                let fetchRequest: NSFetchRequest<PersistentConversationDataItem> = PersistentConversationDataItem.fetchRequest()
               
                let cachedResults = try! coreDataContext.fetch(fetchRequest)
    
                cachedResults.forEach { coreDataContext.delete($0) }
                save()
}


class  Manager {
    
    let coreDataContext: NSManagedObjectContext
    
    init(withContext context: NSManagedObjectContext = CoreDataManager.shared.viewContext) {
        coreDataContext = context
    }
    
    func save() {
        DispatchQueue.main.async {
            if self.coreDataContext.hasChanges {
                do {
                    try self.coreDataContext.save()
                } catch {
                    if let error = error as NSError? {
                        print("U \(error), \(error.userInfo)")
                    }
                }
            }
        }
    }
    
}

crash messsage: *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x600000e76880> was mutated while being enumerated.'


Solution

  • You're iterating over cachedResults and modifying the coreDataContext by deleting objects. This can lead to problems if cachedResults is backed by a collection that's affected by these deletions.

    To fix this, you can try a couple of approaches:

    1. Use a Copy of the Collection for Iteration

    Create a copy of the collection that you'll iterate over, so that modifying the original collection won't affect the iteration.

    let resultsCopy = Array(cachedResults)
    resultsCopy.forEach { coreDataContext.delete($0) }
    
    1. Avoid Using forEach for Mutating Operations

    Instead of using forEach, use a standard for loop, which might handle mutations better in this context.

    for item in cachedResults {
        coreDataContext.delete(item)
    }