重置CoreData持久性存储

cha*_*lax 16 iphone multithreading core-data

基本上,我要做的是擦除CoreData持久存储中的所有数据,然后导入新数据.你会怎么做?似乎最简单的解决方案是调用[NSPersistentStoreCoordinator removePersistentStore:error:]然后删除文件.这是最好的做法吗?它是线程安全的吗?

非常感谢你,

#

问题0.1:是

我正在尝试更新CoreData持久性存储中的数据.我的用户正在查看包含统计数据的表格视图.我想通过删除所有现有数据,然后导入新数据来更新应用程序.我想显示一个进度视图,告诉用户应用程序没有挂起.

resetPersistentStore在AppDelegate中添加了以下方法(persistentStoreCoordinator供参考):

// ...
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
// ...

/**
 Returns the persistent store coordinator for the application.
 If the coordinator doesn't already exist, it is created and the application's store added to it.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: kPersistentStoreFilename]];

    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return persistentStoreCoordinator;
}

/**
 * Will remove the persistent store
 */
- (NSPersistentStoreCoordinator *)resetPersistentStore {
    NSError *error;

    [managedObjectContext lock];

    // FIXME: dirty. If there are many stores...
    NSPersistentStore *store = [[persistentStoreCoordinator persistentStores] objectAtIndex:0];

    if (![persistentStoreCoordinator removePersistentStore:store error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }  

    // Delete file
    if (![[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    } 

    // Delete the reference to non-existing store
    [persistentStoreCoordinator release];
    persistentStoreCoordinator = nil;

    NSPersistentStoreCoordinator *r = [self persistentStoreCoordinator];
    [managedObjectContext unlock];

    return r;
}
Run Code Online (Sandbox Code Playgroud)

然后在我看来我做(在我使用的另一个线程中MBProgressHUD:

PatrimoineAppDelegate *appDelegate = (PatrimoineAppDelegate *)[[UIApplication sharedApplication] delegate]; 
// Delete everything
[appDelegate resetPersistentStore];
Run Code Online (Sandbox Code Playgroud)

我得到了EXC_BAD_ACESS...

我不太了解CoreData或多线程,也许我正在做一个明显的错误......

Phi*_*den 10

对于那些在iOS9 +上尝试此操作的人来说,现在有了destroyPersistentStoreAtURLreplacePersistentStoreAtURLAPI.

  • 您知道任何解释如何使用这些方法的信息吗?苹果的文档很少。 (2认同)
  • 特别不确定哪些选项适用,因为文档根本没有说明 (2认同)

Gia*_*iao 8

如果您的目标是清空数据存储并使用新信息重新加载它,那么最好使用NSManagedObjectContext reset然后加载新数据.

来自NSManagedObjectContext的文档

上下文始终具有"父"持久性存储协调器,其提供模型并将请求分派给包含数据的各种持久性存储.如果没有协调员,上下文就不能完全发挥作用.上下文的协调器提供托管对象模型并处理持久性.从外部存储获取的所有对象都与全局标识符(NSManagedObjectID的实例)一起注册在上下文中,该标识符用于唯一标识外部存储的每个对象.

删除持久性存储并使用与存储关联的托管对象上下文可能是导致错误的原因.

  • 只是为了确保理解:我的数据已经保存在持久性存储中.一个简单的`[moc reset]`(后跟保存)也会擦除sqlite文件中的所有内容? (2认同)
  • 无论如何,重置上下文根本不会改变商店的内容。它只是删除了加载到上下文中的所有内容。 (2认同)

小智 5

还是不行!由具有无效持久性存储的ManagedObjectContext链接导致的中止.最后,如果我删除ManagedObjectContext并让应用程序稍后重新创建它

这是我的修改

- (NSPersistentStoreCoordinator *)resetPersistentStore 
{
  NSError *error = nil;

  if ([persistentStoreCoordinator_ persistentStores] == nil)
    return [self persistentStoreCoordinator];

  [managedObjectContext_ release];
  managedObjectContext_ = nil;

  // FIXME: dirty. If there are many stores...
  NSPersistentStore *store = [[persistentStoreCoordinator_ persistentStores] lastObject];

  if (![persistentStoreCoordinator_ removePersistentStore:store error:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
  }  

  // Delete file
  if ([[NSFileManager defaultManager] fileExistsAtPath:store.URL.path]) {
    if (![[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:&error]) {
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
      abort();
    } 
  }

  // Delete the reference to non-existing store
  [persistentStoreCoordinator_ release];
  persistentStoreCoordinator_ = nil;

  NSPersistentStoreCoordinator *r = [self persistentStoreCoordinator];

  return r;
}
Run Code Online (Sandbox Code Playgroud)