xcode 清理(删除)MagicalRecord 中的数据库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14069563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Clean (remove) a database in MagicalRecord
提问by Hugo
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.
我有一个使用 MagicalRecord 进行核心数据处理的应用程序,这很好用。但是我有不同的用户可以登录应用程序,当另一个用户登录时,必须清空核心数据数据库,以便不同的用户可以拥有自己的数据。数据库可以完全清空,因为数据也存储在网络服务上,因此在第一个用户再次登录后始终可以再次同步。
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.
每当用户注销时,但这并不能解决问题。
回答by yoninja
This is how I did it. It is essential to have this line: [MagicalRecord cleanup]
. Without it, [self setupDB]
won't work.
我就是这样做的。有这条线是必不可少的:[MagicalRecord cleanup]
。没有它,[self setupDB]
将无法工作。
UPDATE:Deletes the -wal and -shm files. @thattyson pointed out an issue in iOS 9. Also, see the answer of @onmyway133.
更新:删除 -wal 和 -shm 文件。@thattyson 指出了 iOS 9 中的一个问题。另外,请参阅@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:
这是 Swift 版本:
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)")
}
}
回答by onmyway133
To expand on @yoninja 's answer, this will make reset CoreData stack explicitly, plus dealing with wal and shm files
为了扩展@yoninja 的答案,这将显式重置 CoreData 堆栈,并处理 wal 和 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);
}
}
回答by casademora
MagicalRecord does not provide this functionality for you. The cleanUp
method is provided for you to reinitialize your CoreData stack in memory and cleaning up any contexts, queues and other related objects. However, it is not that difficult to do yourself given that MagicalRecord does provide a handy method to get the path for your library.
MagicalRecord 不为您提供此功能。该cleanUp
方法提供给您在内存中重新初始化 CoreData 堆栈并清理任何上下文、队列和其他相关对象。但是,鉴于 MagicalRecord 确实提供了一种方便的方法来获取库的路径,所以自己做并不难。
Check out the -[NSPersistentStore MR_urlForStoreName:]
method. This will give you the file url for your store. You can then delete it with an NSFileManager
instance. Be careful to do this before you set up the Core Data stack or you'll crash when you save because you'd have yanked out the store from under a properly initialized stack.
检查-[NSPersistentStore MR_urlForStoreName:]
方法。这将为您提供商店的文件 url。然后,您可以使用NSFileManager
实例将其删除。在设置 Core Data 堆栈之前要小心执行此操作,否则在保存时会崩溃,因为您会从正确初始化的堆栈下拉出存储。
回答by RyanG
The following will completely delete the MagicalRecord CoreData sqlite files, as well as the -wal and -shm files. MagicalRecord puts them all in the Library folder; this will simply remove all files from the folder. This will not work if you have other data you need to persist in the Library folder, I did not:
以下将完全删除 MagicalRecord CoreData sqlite 文件,以及 -wal 和 -shm 文件。MagicalRecord 将它们全部放在 Library 文件夹中;这将简单地从文件夹中删除所有文件。如果您有其他数据需要保留在 Library 文件夹中,这将不起作用,我没有:
- (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);
}
}
}
回答by Nate Hat
If you are using the iOS Simulator and deleted the database file, you may probably notice that the data is still there. However, if tested on an actual device (which should be), the file is deleted and the context is reset as should be.
如果您使用的是 iOS 模拟器并删除了数据库文件,您可能会注意到数据仍然存在。但是,如果在实际设备上进行测试(应该如此),则会删除文件并按原样重置上下文。
[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"];
回答by Eridana
A bit rewritten answer of @yoninja for Swift 4:
@yoninja 为Swift 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)")
}
}