2012-12-28 57 views
14

我有一个使用MagicalRecord进行核心数据处理的应用程序,这很好。但是,我有不同的用户可以在应用程序中登录,并且当其他用户登录时,必须清空核心数据数据库,以便不同的用户可以拥有自己的数据。数据库可以完全清空,因为数据也存储在web服务上,因此可以在再次登录第一个用户后再次同步。清理(删除)MagicalRecord中的数据库

到目前为止,我似乎无法找到一个辅助方法(工程)为此目的。我试过

[MagicalRecord cleanUp]; 

无论何时用户注销,但这并没有办法。

+2

我不知道神奇记录有东西来管理这一点。你需要等待作者。无论如何,你可以简单地绕过它删除创建的数据库文件,并通过MagicalRecord重新初始化堆栈。也许,你可以在MagicalRecord项目中打开一个pull请求(需要GitHub帐户)。 –

回答

17

MagicalRecord不为您提供此功能。您可以使用cleanUp方法将CoreData堆栈重新初始化到内存中,并清除所有上下文,队列和其他相关对象。但是,由于MagicalRecord确实提供了一种方便的方法来获取库的路径,所以这并不难。

检查出-[NSPersistentStore MR_urlForStoreName:]方法。这会为您提供商店的文件网址。然后,您可以使用NSFileManager实例将其删除。在设置核心数据堆栈之前要小心,否则在保存时会崩溃,因为您已经从正确初始化的堆栈中抽出了存储。

+0

如果你看到我的评论我建议同样的事情;-) +1为你的更深的解释 –

+0

您的建议拉回要求或回购问题也欢迎:) – casademora

+0

我刚刚在GitHub上插入一个新问题。干杯。 –

36

这就是我做到的。有这条线是必不可少的:[MagicalRecord cleanup]。没有它,[self setupDB]将无法​​正常工作。

更新:删除-wal和-shm文件。 @thattyson在iOS 9中指出了一个问题。另请参阅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); 
    } 
} 

这里的雨燕版本:

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)") 
    } 
} 
+3

但是-shm和-wal-files怎么样?这些不会被删除,对吧? – swalkner

+1

不适合我。我收到以下错误:“操作无法完成。没有这样的文件或目录” – Szu

+0

从iOS9起,如果您不删除-shm和-wal文件,您的应用程序将崩溃,出现错误“SQLite错误代码:522 '尝试第二次安装数据库后。 – thattyson

2

如果您使用的是iPhone模拟器并删除了数据库文件,你可能会注意到,该数据仍然存在。但是,如果在实际设备(应该是)上进行测试,文件将被删除并且上下文被重置。

[MagicalRecord cleanUp]; 

// delete database file 
NSError *error; 
NSURL *fileURL = [NSPersistentStore MR_urlForStoreName:@"db.sqlite"]; 
[[NSFileManager defaultManager] removeItemAtURL:fileURL error:&error]; 
if(error) { 
    // Hanldle error 
} 

// reset setup. 
[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"db.sqlite"]; 
+0

在iOS 9后,然后使应用程序崩溃,数据库会丢失.. –

5

以下将完全删除MagicalRecord CoreData sqlite文件以及-wal和-shm文件。 MagicalRecord将它们全部放入库文件夹中;这将只是从文件夹中删除所有文件。如果你有你需要的库文件夹坚持其他数据这样可不行,我没有:

- (void)resetCoreDataDB 
{ 
    [MagicalRecord cleanUp]; 
    [self deleteFilesInLibrary]; 
    [MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"YourDBName.sqlite"]; 
} 

- (void)deleteFilesInLibraryDirectory 
{ 
    NSString* folderPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSError *error = nil; 
    for (NSString *file in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:&error]) 
    { 
     [[NSFileManager defaultManager] removeItemAtPath:[folderPath stringByAppendingPathComponent:file] error:&error]; 
     if(error) 
     { 
      NSLog(@"Delete error: %@", error.description); 
     } 
    } 
} 
20

要扩大@yoninja的回答,这将使明确重置CoreData堆栈,以及处理与沃尔玛和SHM文件

- (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); 
    } 
} 
+0

谢谢,它适用于我 – lenhhoxung

+0

这也适用于我,但它似乎有时后台线程上的私人上下文悬而未决登出。任何想法如何我可以解决这个问题?感谢你的帮助。 – Myxtic

+0

谢谢!你救了我! –

0

有点改写@yoninja的答案斯威夫特4

private var dbStore : String? { 
    get { 
     if let bundleId = Bundle.main.bundleIdentifier { 
      return bundleId + ".sqlite" 
     } 
     return MagicalRecord.defaultStoreName() 
    } 
} 

func setupCoreDataStack() { 
    MagicalRecord.setupCoreDataStack(withAutoMigratingSqliteStoreNamed: self.dbStore) 
} 

func cleanUp() {   
    MagicalRecord.cleanUp() 

    var removeError: NSError? 
    let deleteSuccess: Bool 
    do { 
     guard let url = NSPersistentStore.mr_url(forStoreName: self.dbStore) else { 
      return 
     } 
     let walUrl = url.deletingPathExtension().appendingPathExtension("sqlite-wal") 
     let shmUrl = url.deletingPathExtension().appendingPathExtension("sqlite-shm") 

     try FileManager.default.removeItem(at: url) 
     try FileManager.default.removeItem(at: walUrl) 
     try FileManager.default.removeItem(at: shmUrl) 

     deleteSuccess = true 
    } catch let error as NSError { 
     removeError = error 
     deleteSuccess = false 
    } 

    if deleteSuccess { 
     self.setupCoreDataStack() 
    } else { 
     print("An error has occured while deleting \(self.dbStore)") 
     print("Error description: \(removeError.debugDescription)") 
    } 
}