Group Group Group Group Group Group Group Group Group

CoreData SQLite Journaling Mode

Seems like the code from the book needs an update:

  // 5 (6. Versioning & Migration)
  if success {
    print("Migration Completed Successfully")

    let fileManager = FileManager.default
    do {
        try fileManager.removeItem(at: storeURL)
        try fileManager.moveItem(
          at: destinationURL,
          to: storeURL
        )
    } catch {
  	  print("Error migrating \(error)")
  	}
  }

With this (original) code my app crashes after successful migration due to corrupt data store.
Apple uses SQLite Journaling Mode in recent iOS versions:

https://developer.apple.com/library/archive/qa/qa1809/_index.html

I’ve added some quick and dirty hack:

        if success {
            print("Migration Completed Successfully")

            let fileManager = FileManager.default
            do {
                try fileManager.removeItem(at: storeURL)
                try fileManager.moveItem(
                    at: destinationURL,
                    to: storeURL
                )

                // Replaces Journaling Mode Files if they exist
                //
                // See: https://developer.apple.com/library/archive/qa/qa1809/_index.html
                try? fileManager
                    .removeItem(at: storeURL.deletingLastPathComponent()
                        .appendingPathComponent("\(storeURL.lastPathComponent)-shm"))
                try? fileManager.moveItem(
                    at: destinationURL.deletingLastPathComponent()
                        .appendingPathExtension("\(destinationURL.lastPathComponent)-shm"),
                    to: storeURL.deletingLastPathComponent()
                        .appendingPathComponent("\(storeURL.lastPathComponent)-shm")
                )
                try? fileManager
                    .removeItem(at: storeURL.deletingLastPathComponent()
                        .appendingPathComponent("\(storeURL.lastPathComponent)-wal"))
                try? fileManager.moveItem(
                    at: destinationURL.deletingLastPathComponent()
                        .appendingPathComponent("\(destinationURL.lastPathComponent)-wal"),
                    to: storeURL.deletingLastPathComponent()
                        .appendingPathComponent("\(storeURL.lastPathComponent)-wal")
                )
            } catch {
                print("Error migrating \(error)")
            }
        }

This solves the issue for me.
Maybe you want to review + improve the changes; then update the book.

There are better ways of doing it. I ended up doing it like this:

if success {
    print("Migration Completed Successfully")
    do {
        let pc = NSPersistentContainer(name: modelName)
        let psc = pc.persistentStoreCoordinator
        try psc.replacePersistentStore(
            at: storeURL,
            destinationOptions: nil,
            withPersistentStoreFrom: destinationURL,
            sourceOptions: nil,
            ofType: NSSQLiteStoreType
        )
        try psc.destroyPersistentStore(
            at: destinationURL,
            ofType: NSSQLiteStoreType,
            options: nil
        )
    } catch {
        print("Failed to replace \(storeURL)")
    }
}