Clean (remove) a database in MagicalRecord

Hugo picture Hugo · Dec 28, 2012 · Viewed 13.4k times · Source

I have an app that is using MagicalRecord for its Core Data handling and this works nice. However I have different users that can login in the app and when another user logs in, the core data database must be emptied so that the different user can have his own data. The database can be emptied completely as the data is also stored on a webservice and therefore can always be synced again after logging in again the first user.

So far I cannot seem to find a helper method (that works) for this purpose. I have tried

[MagicalRecord cleanUp];

whenever the user is logging out, but this does not do the trick.

Answer

yoninja picture yoninja · Aug 2, 2013

This is how I did it. It is essential to have this line: [MagicalRecord cleanup]. Without it, [self setupDB] won't work.

UPDATE: Deletes the -wal and -shm files. @thattyson pointed out an issue in iOS 9. Also, see the answer of @onmyway133.

- (void)setupDB
{
    [MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:[self dbStore]];
}

- (NSString *)dbStore
{
    NSString *bundleID = (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];
    return [NSString stringWithFormat:@"%@.sqlite", bundleID];
}

- (void)cleanAndResetupDB
{
    NSString *dbStore = [self dbStore];

    NSError *error1 = nil;
    NSError *error2 = nil;
    NSError *error3 = nil;

    NSURL *storeURL = [NSPersistentStore MR_urlForStoreName:dbStore];
    NSURL *walURL = [[storeURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"sqlite-wal"];
    NSURL *shmURL = [[storeURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"sqlite-shm"];

    [MagicalRecord cleanUp];

    if([[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error1] && [[NSFileManager defaultManager] removeItemAtURL:walURL error:&error2] && [[NSFileManager defaultManager] removeItemAtURL:shmURL error:&error3]){
        [self setupDB];
    }
    else{
        NSLog(@"An error has occurred while deleting %@", dbStore);
        NSLog(@"Error1 description: %@", error1.description);
        NSLog(@"Error2 description: %@", error2.description);
        NSLog(@"Error3 description: %@", error3.description);
    }
}

Here's the Swift version:

func setupDB() {
    MagicalRecord.setupCoreDataStackWithAutoMigratingSqliteStoreNamed(self.dbStore())
}

func dbStore() -> String {
    return "\(self.bundleID()).sqlite"
}

func bundleID() -> String {
    return NSBundle.mainBundle().bundleIdentifier!
}

func cleanAndResetupDB() {
    let dbStore = self.dbStore()

    let url = NSPersistentStore.MR_urlForStoreName(dbStore)
    let walURL = url.URLByDeletingPathExtension?.URLByAppendingPathExtension("sqlite-wal")
    let shmURL = url.URLByDeletingPathExtension?.URLByAppendingPathExtension("sqlite-shm")

    var removeError: NSError?

    MagicalRecord.cleanUp()

    //Swift 1
    //let deleteSuccess = NSFileManager.defaultManager().removeItemAtURL(url, error: &removeError)

    //Swift 2
    let deleteSuccess: Bool
    do {
        try NSFileManager.defaultManager().removeItemAtURL(url)
        try NSFileManager.defaultManager().removeItemAtURL(walURL!)
        try NSFileManager.defaultManager().removeItemAtURL(shmURL!)
        deleteSuccess = true
    } catch let error as NSError {
        removeError = error
        deleteSuccess = false
    }

    if deleteSuccess {
        self.setupDB()
    } else {
        println("An error has occured while deleting \(dbStore)")
        println("Error description: \(removeError?.description)")
    }
}