NSManagedObjectContext+Sweeter.swift 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. //
  2. // NSManagedObjectContext+Sweeter.swift
  3. //
  4. // Created by Yonat Sharon on 2019-02-08.
  5. //
  6. import CoreData
  7. public extension NSManagedObjectContext {
  8. /// Sweeter: Names of all entities in the object model associated with the receiver
  9. var allEntityNames: [String] {
  10. return persistentStoreCoordinator?.managedObjectModel.entities.compactMap(\.name) ?? []
  11. }
  12. /// Sweeter: Delete all objects, or all objects of specific entity name(s).
  13. func deleteAllObjects(entityName: String...) throws {
  14. let entityNames = entityName.isEmpty ? allEntityNames : entityName
  15. for entityName in entityNames {
  16. let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
  17. let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
  18. try execute(deleteRequest)
  19. }
  20. }
  21. /// Sweeter: Dump contents to console - for debugging
  22. func printAllObjects(entityName: String...) {
  23. let entityNames = entityName.isEmpty ? allEntityNames : entityName
  24. for entityName in entityNames {
  25. guard let objects = try? fetch(NSFetchRequest<NSFetchRequestResult>(entityName: entityName)) else { continue }
  26. print("== \(entityName) (\(objects.count)) ==")
  27. for object in objects {
  28. print(String(describing: object))
  29. }
  30. }
  31. }
  32. /// Sweeter: Create a copy of the store for backup or for using later as initial setup
  33. func backupStore() {
  34. guard let persistentStoreCoordinator = persistentStoreCoordinator else { return }
  35. guard let sourceStore = persistentStoreCoordinator.persistentStores.first else { return }
  36. let backupCoordinator = NSPersistentStoreCoordinator(managedObjectModel: persistentStoreCoordinator.managedObjectModel)
  37. let intermediateStoreOptions = (sourceStore.options ?? [:]).merging([NSReadOnlyPersistentStoreOption: true], uniquingKeysWith: { $1 })
  38. guard let intermediateStore = try? backupCoordinator.addPersistentStore(
  39. ofType: sourceStore.type,
  40. configurationName: sourceStore.configurationName,
  41. at: sourceStore.url,
  42. options: intermediateStoreOptions
  43. ) else { return }
  44. let backupStoreOptions: [AnyHashable: Any] = [
  45. NSReadOnlyPersistentStoreOption: true,
  46. // Disable write-ahead logging so that the entire store will be
  47. // contained in a single file. No need to handle -wal/-shm files.
  48. // https://developer.apple.com/library/content/qa/qa1809/_index.html
  49. NSSQLitePragmasOption: ["journal_mode": "DELETE"],
  50. // Minimize file size
  51. NSSQLiteManualVacuumOption: true,
  52. ]
  53. let basename = sourceStore.url?.deletingPathExtension().lastPathComponent ?? "store"
  54. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last ?? URL(fileURLWithPath: ".")
  55. let backupURL = documentsDirectory.appendingPathComponent("\(basename)-backup.sqlite")
  56. print("Backed up store to " + backupURL.path)
  57. _ = try? backupCoordinator.migratePersistentStore(intermediateStore, to: backupURL, options: backupStoreOptions, withType: NSSQLiteStoreType)
  58. }
  59. }