我有一个使用MagicalRecord进行核心数据处理的应用程序,这很好。但是,我有不同的用户可以在应用程序中登录,并且当其他用户登录时,必须清空核心数据数据库,以便不同的用户可以拥有自己的数据。数据库可以完全清空,因为数据也存储在web服务上,因此可以在再次登录第一个用户后再次同步。清理(删除)MagicalRecord中的数据库
到目前为止,我似乎无法找到一个辅助方法(工程)为此目的。我试过
[MagicalRecord cleanUp];
无论何时用户注销,但这并没有办法。
我有一个使用MagicalRecord进行核心数据处理的应用程序,这很好。但是,我有不同的用户可以在应用程序中登录,并且当其他用户登录时,必须清空核心数据数据库,以便不同的用户可以拥有自己的数据。数据库可以完全清空,因为数据也存储在web服务上,因此可以在再次登录第一个用户后再次同步。清理(删除)MagicalRecord中的数据库
到目前为止,我似乎无法找到一个辅助方法(工程)为此目的。我试过
[MagicalRecord cleanUp];
无论何时用户注销,但这并没有办法。
MagicalRecord不为您提供此功能。您可以使用cleanUp
方法将CoreData堆栈重新初始化到内存中,并清除所有上下文,队列和其他相关对象。但是,由于MagicalRecord确实提供了一种方便的方法来获取库的路径,所以这并不难。
检查出-[NSPersistentStore MR_urlForStoreName:]
方法。这会为您提供商店的文件网址。然后,您可以使用NSFileManager
实例将其删除。在设置核心数据堆栈之前要小心,否则在保存时会崩溃,因为您已经从正确初始化的堆栈中抽出了存储。
这就是我做到的。有这条线是必不可少的:[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)")
}
}
如果您使用的是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"];
在iOS 9后,然后使应用程序崩溃,数据库会丢失.. –
以下将完全删除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);
}
}
}
要扩大@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);
}
}
谢谢,它适用于我 – lenhhoxung
这也适用于我,但它似乎有时后台线程上的私人上下文悬而未决登出。任何想法如何我可以解决这个问题?感谢你的帮助。 – Myxtic
谢谢!你救了我! –
有点改写@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)")
}
}
我不知道神奇记录有东西来管理这一点。你需要等待作者。无论如何,你可以简单地绕过它删除创建的数据库文件,并通过MagicalRecord重新初始化堆栈。也许,你可以在MagicalRecord项目中打开一个pull请求(需要GitHub帐户)。 –