简体   繁体   中英

Should I delete underlying persistent store files after calling destroyPersistentStore on a NSPersistentStoreCoordinator?

I'm migrating my iOS app to use NSPersistentContainer . This class by default locates its persistent store files in the Library/Application Support directory; previously my store files were stored in the Documents directory.

I've added a little bit of code to move the store files if they were found at the old directory:

func moveStoreFromLegacyLocationIfNecessary(toNewLocation newLocation: URL) {

    // The old store location is in the Documents directory
    let legacyStoreLocation = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("books.sqlite")

    // Check whether the old store exists and the new one does not
    if FileManager.default.fileExists(atPath: legacyStoreLocation.path) && !FileManager.default.fileExists(atPath: newLocation.path) {

        print("Store located in Documents directory; migrating to Application Support directory")
        let tempStoreCoordinator = NSPersistentStoreCoordinator()
        try! tempStoreCoordinator.replacePersistentStore(at: newLocation, destinationOptions: nil, withPersistentStoreFrom: legacyStoreLocation, sourceOptions: nil, ofType: NSSQLiteStoreType)

        // Delete the old store
        try? tempStoreCoordinator.destroyPersistentStore(at: legacyStoreLocation, ofType: NSSQLiteStoreType, options: nil)
    }
}

After calling destroyPersistentStore(at: url) , the store files are still present on disk. Will these be automatically cleaned up at some point? Or should I be deleting them? Should I also be deleting the .sqlite-shm and .sqlite-wal files?

The documentation for NSPersistentStoreCoordinator.destroyPersistentStore(at:type:options:) states:

Deletes a specific type of persistent store at the provided location.

In talking with an engineer in a WWDC lab, they explained it does not actually delete the database files at the provided location as the documentation seems to imply. It actually just truncates rather than delete. If you want them gone you can manually delete the files (if you can ensure no other process or a different thread is accessing them).

This is what I've implemented in my app:

try coordinator.replacePersistentStore(at: sharedStoreURL, destinationOptions: nil, withPersistentStoreFrom: defaultStoreURL, sourceOptions: nil, ofType: NSSQLiteStoreType)
try coordinator.destroyPersistentStore(at: defaultStoreURL, ofType: NSSQLiteStoreType, options: nil)

// destroyPersistentStore says it deletes the old store but it actually truncates so we'll manually delete the files
NSFileCoordinator(filePresenter: nil).coordinate(writingItemAt: defaultStoreURL.deletingLastPathComponent(), options: .forDeleting, error: nil, byAccessor: { url in
    try? FileManager.default.removeItem(at: defaultStoreURL)
    try? FileManager.default.removeItem(at: defaultStoreURL.deletingLastPathComponent().appendingPathComponent("\(container.name).sqlite-shm"))
    try? FileManager.default.removeItem(at: defaultStoreURL.deletingLastPathComponent().appendingPathComponent("\(container.name).sqlite-wal"))
    try? FileManager.default.removeItem(at: defaultStoreURL.deletingLastPathComponent().appendingPathComponent("ckAssetFiles"))
})

I filed FB10181832 to request the documentation be updated to better explain its behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM