【问题标题】:Clearing CoreData and all that inside清除 CoreData 和里面的所有东西
【发布时间】:2013-02-06 11:10:09
【问题描述】:

我对 CoreData 和使用它的这个应用程序还是很陌生。 我目前正在开发一个功能,当我在应用程序中注销时清除整个核心数据。

我有 2 个 sqllite 文件(出于某种原因,他们认为这很方便)

如何清除两个文件的所有数据并将它们重置为无数据状态?

我已经尝试了很多方法,遵循指南,关于 SO。

How to clear/reset all CoreData in one-to-many relationship

how to remove all objects from Core Data

他们对我来说似乎都失败了。 现在我想知道我做错了什么?也许有人可以解释我如何以正确的方式重置我的 2 个 CoreData 文件。

编辑:

//should clear the whole coredata database. mainly used for logout mechanism
-(void)resetCoreData
{
    for (NSPersistentStore *store in self.persistentStoreCoordinator.persistentStores)
    {
//    NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores[0];
        NSError *error;
        NSURL *storeURL = store.URL;
        DLog(@"storeURL: %@", storeURL);
        NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
        [storeCoordinator removePersistentStore:store error:&error];
        [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

        DLog(@"There are erreurs: %@", error);
//    [self addDefaultData];
    }

    _persistentStoreCoordinator = nil;
    _managedObjectContext = nil;
    _managedObjectModel = nil;
}

这似乎没有为我清除 CoreData。

EDIT2:

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil) {
        return __managedObjectModel;
    }

    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyName" withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    return __managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

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

    NSString *storePath = [[self applicationDocumentsDirectory]

                           stringByAppendingPathComponent:@"MyName.sqlite"];

    NSFileManager *fileManager = [NSFileManager defaultManager];

    // If the expected store doesn't exist, copy the default store.
    if (![fileManager fileExistsAtPath:storePath]) {
        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"MyName" ofType:@"momd"];
        if (defaultStorePath) {

            [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];

        }

    }



    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

    //Check to see what version of the current model we're in. If it's >= 2.0,
    //then and ONLY then check if migration has been performed...
    NSSet *versionIdentifiers = [[self managedObjectModel] versionIdentifiers];
    DLog(@"Which Current Version is our .xcdatamodeld file set to? %@", versionIdentifiers);

    if ([versionIdentifiers containsObject:@"2.0"])
    {
        BOOL hasMigrated = YES;
        if (hasMigrated==YES) {
            storePath = nil;
            storePath = [[self applicationDocumentsDirectory]
                         stringByAppendingPathComponent:@"MyName2.sqlite"];

        }
    }

    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
    NSError *error;
    NSDictionary *pscOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                [NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption,
                                nil];

    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                    configuration:nil
                                                              URL:storeUrl
                                                          options:pscOptions
                                                            error:&error]) {
        DLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return __persistentStoreCoordinator;
}

编辑 3: 我仍在寻找一种方法来重置我的 CoreData,就好像我删除了整个应用程序并重新启动它一样。这样做的通常方法不适用于我的情况。并且有 2 个 sqllite 文件。有迹象表明在应用程序的某个时间点发生了迁移,但我不太确定何时以及如何迁移。错误日志显示没有任何用处。

我不是在寻找最有效的方法。就是这样。

帮帮我,赏金就是你的了。

编辑 4: 最后结果: 似乎我的旧代码实例化了第二个 ManagedObjectContext。我检索它并使用它执行刷新功能的那一刻。两个 sqlite 文件都根据需要消失了。

感谢所有为我的问题付出的努力。

【问题讨论】:

  • 我能看到的第一件事是,您在循环内将所有 coredata 内容设置为 nil。这需要在循环完成运行后进行。
  • 这两种方法都不起作用。我注意到的是,只有 2 家商店中的一家正在被记录。第二个不在 for 循环内的原因可能是什么?
  • 当你设置核心数据的东西时,它应该只有一个商店。那一家商店将保存您的所有数据(除非您正在做的事情特别需要多个数据)?
  • 都是遗留代码。这一切都是一团糟。我刚刚开始研究这个应用程序。出于某种原因,有 2 个 CoreData SQLLite 文件,并且那里有迁移功能的提示。但我也认为不需要 2 家商店。
  • 啊,我明白了。你有设置和初始化 coredata 堆栈的代码吗?我也许可以尝试破译发生了什么。

标签: objective-c core-data reset


【解决方案1】:

尝试以下方法刷新数据库,它非常适合我。

-(void) flushDatabase{
    [__managedObjectContext lock];
    NSArray *stores = [__persistentStoreCoordinator persistentStores];
    for(NSPersistentStore *store in stores) {
       [__persistentStoreCoordinator removePersistentStore:store error:nil];
       [[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
    }
    [__managedObjectContext unlock];
    __managedObjectModel    = nil;
    __managedObjectContext  = nil;
    __persistentStoreCoordinator = nil;
}

【讨论】:

  • 这与给出的其他答案几乎相同。不幸的是,它们对我不起作用。
  • 做一件事,在flushdatabase方法处应用一个断点,然后去你的“/Library/Application\ Support/iPhone\ Simulator”并使用SQLITEMANAGER或LITA打开数据库并查看数据库条目,当执行flush database方法刷新数据库时,你会看到你的数据库已经完全刷新了。请在您进行此调试时更新我。
  • 我现在正在调试。我有 2 个 sqlite 文件。一个几乎是空的“db2.sqlite”。另一个有我似乎很熟悉的应用程序“db.sqlite”中的数据。在 flush 方法之后,他们都没有删除他的数据。
  • 当你调用 flushdatabase 方法时,我怀疑你没有正确的 managedobjectcontext。
  • 好的!好消息。你是对的。显然,在某处宣布了第二个 MOC 对象。在我访问该对象并将其插入到刷新中的那一刻,我看到 2 个 dbfiles 已从我的查找器中删除,并在我的屏幕上看到了结果。再次为糟糕的遗留代码欢呼……感谢您的帮助,这对我帮助很大。
【解决方案2】:
NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

因此,您正在从持久存储协调器中删除持久存储,然后尝试删除该文件。但是仅从协调器中删除存储并不足以保证与存储关联的文件已关闭,如果尚未关闭,则文件系统可能会阻止您删除该文件。我无法从您的问题中判断您是否在这里使用 ARC,但是既然您说它是旧代码,那么您很有可能不是。无论哪种方式,如果删除存储导致它被自动释放而不是释放,或者如果您在任何地方保留对存储的任何其他引用,那么存储不会因为您从协调器中删除它而被释放,文件可能保持打开状态,删除文件将失败。

查看实际情况的好方法,除了查看-removeItemAtPath:error: 提供的错误对象外,还可以查看文件系统,并在尝试删除文件后查看文件是否仍然存在.转到管理器窗口,选择您的设备和应用程序,然后下载应用程序沙箱的副本。然后您应该能够看到该文件是否真的被删除了。

如果您确实看到文件按照您认为的方式被删除,那么请寻找其他可以恢复数据的方法。如果 UserA 注销然后 UserB 在应用程序仍在运行时登录到应用程序,您确定您已经开始使用新的托管对象上下文吗? UserA 的数据是否可能保留在 MOC 中?然后可以在您创建和添加新商店时将其写出。我想到的另一种可能性是 iCloud 在这里“提供帮助”。我看到您的数据文件保存在 Documents 目录中,iOS 通常会尝试将该目录中的文件备份到 iCloud。也许当您为 UserB 的数据创建新存储时,iCloud 会将 UserA 的记录添加回该存储。 (似乎不太可能——我很确定 iCloud 比这更复杂——但需要检查一下。)

【讨论】:

  • 好的,让我把事情弄清楚一点。 1. 应用中使用了ARC,从不使用release函数和autorelease函数。当我“注销”时,我没有检测到文件系统有任何变化。 iCloud 也不参与。 MOC 是一个不错的选择。我不确定如何在应用程序中进行管理。你能告诉我应该如何管理它吗?
【解决方案3】:

我在我的一个应用程序的 AppDelegate 中使用此功能...

- (void)deleteAllCoreData
{
    NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores[0];
    NSError *error;
    NSURL *storeURL = store.URL;
    NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
    [storeCoordinator removePersistentStore:store error:&error];
    [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

    __persistentStoreCoordinator = nil;
    __managedObjectContext = nil;
    __managedObjectModel = nil;

    [self addDefaultData];
}

它会删除 CoreData 使用的持久存储并将其保留,以便在再次访问核心数据时设置一个新的。

这是您提供的第二个链接中描述的方法。

【讨论】:

  • 是的,好吧。然而问题是它对我不起作用。
  • 什么不起作用?你得到什么错误?你怎么知道它不起作用。
  • 我没有收到任何错误。但是我注意到当我注销并在另一个帐户下重新登录时,存储在前一个帐户的 CoreData 中的所有数据仍然存在并且可见。
  • 您是否在应用启动时重新添加数据?
  • 没有看到任何代码,我无能为力。我发布的代码在我使用它来执行此操作时起作用。如果您的代码中的其他内容未正确设置,则可能会导致问题。
【解决方案4】:

如果您的应用可以创建文件,则只需在应用退出时将其删除。 如果您对具有有价值的架构信息的数据库有一些概念,并且您只需要截断文件,那么核心数据中的情况并非如此......架构位于已编译的实体模型和 xcwhatever 文件中。

另外我一定是看错了,因为如果您希望核心数据不持久,那么您使用的是错误的工具。

【讨论】:

  • 我不同意你最后的说法。 Core Data 比持久性有更多的优势。使用NSInMemoryStoreType 使模型的一部分持久化而另一部分瞬态是正常的。这就是它存在的原因,对吧?
  • Ofc 我希望我的数据是持久的。只是想在您使用帐户注销时将其全部清除。这是一种罕见的情况,但不是我应该忽略的情况。用户在某个时间点注册或登录后会自动登录。并且只能手动注销。这是用户清除该特定用户的本地数据的良心行为。因此,当他重新登录时,我需要为新(或相同)用户做好准备。
  • @iMartin,我猜你可以在没有持久性存储的情况下使用它......也许可以用于撤消管理......但它肯定是一个不那么引人注目的用例。
  • @GradyPlayer 不仅仅是撤销管理:反向关系、KVO、版本控制……(将来可能会使用 iCloud 同步)。我通常很少有实体持久化,其余的都在内存存储中。只需单击几下即可持久保存它们(如果我决定这样做),无需修改任何内容。
  • 我不是核心数据的批评者,但你从核心数据中获得的所有其他东西对于实现来说都是微不足道的,并且不得不在单个线程上运行所有东西或执行锁定带来沉重的代价,或者疯狂的合并通知更新。
猜你喜欢
  • 2015-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多