Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clean (remove) a database in MagicalRecord

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.

like image 802
Hugo Avatar asked Dec 28 '12 12:12

Hugo


2 Answers

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)")
    }
}
like image 130
yoninja Avatar answered Nov 16 '22 02:11

yoninja


To expand on @yoninja 's answer, this will make reset CoreData stack explicitly, plus dealing with wal and shm files

- (void)setupDB
{
    [MagicalRecord setDefaultModelNamed:@"Model.momd"];
    [MagicalRecord setupCoreDataStack];
}

- (void)cleanAndResetupDB
{
    [MagicalRecord cleanUp];

    NSString *dbStore = [MagicalRecord defaultStoreName];

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

    NSError *error = nil;
    BOOL result = YES;

    for (NSURL *url in @[storeURL, walURL, shmURL]) {
        if ([[NSFileManager defaultManager] fileExistsAtPath:url.path]) {
            result = [[NSFileManager defaultManager] removeItemAtURL:url error:&error];
        }
    }

    if (result) {
        [self setupDB];
    } else {
        NSLog(@"An error has occurred while deleting %@ error %@", dbStore, error);
    }
}
like image 27
onmyway133 Avatar answered Nov 16 '22 00:11

onmyway133