【问题标题】:How to customise save in Core Data?如何在 Core Data 中自定义保存?
【发布时间】:2013-10-11 16:57:04
【问题描述】:

我为我的项目定义了一个核心数据并实现了一个名为isRealEntry 的实体:属性。

@interface FTRecord : NSManagedObject

@property (nonatomic) NSTimeInterval lastUpdated;
@property (nonatomic) BOOL isRealEntry;

@end

现在当我保存上下文时 (NSManagedObjectContext *context;)

NSError *error = nil;
BOOL successful = [context save:&error];

我只想保存那些具有真实isRealEntry 的实体,否则该条目将被忽略或撤消。

我怎样才能做到这一点?

更新:

起初我发现 Martin 的解决方案很有前景。但是,当我在进入后台保存数据时,会产生非常讨厌的副作用:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [[FTRecordStore sharedStore] saveChanges];
}

当我恢复应用程序时,之前删除的所有记录并没有真正消失,而是标记为删除。该数组似乎仍然拥有所有这些(在我的情况下是真实的或不真实的)。单元格完全疯了,所有记录都显示为空。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    FTRecord *record = [[[FTRecordStore sharedStore] getAllRecords] objectAtIndex:[indexPath row]];

FTRecordCellView *cell = [tableView dequeueReusableCellWithIdentifier:@"FTRecordCellView"];

    [[cell notesLabel] setText:[record notes]];

return cell;
}

我不知道如何解决这个问题。我的商店是单身人士。 getAllRecords 确定每个单元格的内容。因此,我需要为 getAllRecords 设置与 tableView 中相同的值,否则它会崩溃。

另一种建议的解决方案在内存和数据库中有两个来源似乎也不可能,我如何为一个 TableView 提供两个来源?

更新 2:

我有一个令人尴尬的疏忽。从上下文中删除记录是不够的。我还必须从数组中删除它。

[allRecords removeObjectIdenticalTo:record];

因此我收回了它。 Martin 的解决方案非常完美。但是,我仍然很想知道 UITableView 是否确实可以按照其他解决方案中的建议从两个源(数据库/内存)驱动。谢谢

【问题讨论】:

    标签: ios ios7


    【解决方案1】:

    我之前不得不做类似的事情,我处理它的方法是为我要持久化的项目提供一个单独的托管对象上下文,而另一个只为那些只保留在内存中的项目。

    我通过拥有一个单独的持久存储协调器以及一个仅在内存中的单独的托管对象上下文来解决这个问题,因此当将项目保存到其中时,它们不会像您所描述的那样持久化到数据库中实物。

    您可以像这样创建内存持久存储协调器:

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

    [inMemoryPersistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType 配置:nil URL:nil 选项:nil 错误:&error];

    如果您想将非真实项目更改为真实项目,您可以将它们复制到其他托管对象上下文中,该上下文将在保存项目时将项目持久保存到数据库中。

    这里明显的问题是搜索是在单个托管对象上下文中完成的,因此如果您希望搜索持久对象和内存对象,那么您需要按照 Arkadiusz 在他的回答中建议的内容做更多的事情。

    【讨论】:

    • +1。你甚至可以使用一个上下文、一个持久存储协调器和两个存储(sqlite +在内存中),然后将对象与一个存储关联或其他:stackoverflow.com/a/14005159/1187415。 - 显然,我已经忘记了一年前自己的答案 :-)
    • 谢谢马丁,很好的补充!我没有意识到你可以做到这一点
    • 虽然这是一个有效的解决方案,但我相信 Martin 的其他解决方案(我接受它作为答案)并不那么复杂。覆盖WillSave 远比控制两组存储更可行。 :)
    【解决方案2】:

    保存托管对象上下文会保存对该上下文所做的所有更改。你不能 从保存操作中排除一些对象。

    要撤消对“虚幻”对象的所有更改,您可以实现willSave NSManagedObject 子类的方法:

    - (void)willSave
    {
        if (![self.isRealEntry boolValue]) {
            if (self.isInserted) {
                // Object was inserted, remove it again:
                [self.managedObjectContext deleteObject:self];
            } else if (self.isUpdated) {
                // Object was modified, undo all changes:
                [self.managedObjectContext refreshObject:self mergeChanges:NO];
            }
        }
    }
    

    (我从未在实际项目中这样做过,但我构建了一个小型测试应用程序并 它似乎有效。)

    【讨论】:

    • 抱歉,马丁,正如您警告的那样,这导致了一些问题,我在更新中已经给出了这些问题。你对 UITableView 共享两个源(内存/db)有什么其他想法吗?
    • @Kave:看看stackoverflow.com/questions/14004055/…。这与 Duncan 的建议类似,但仅使用一个托管对象上下文和两个存储:“真实”对象分配给 SQLite 存储,而“非真实”对象分配给内存存储。
    【解决方案3】:

    我不相信有内置的方法可以做到这一点。我相信您要么必须在保存之前删除它们,要么编写清理代码以便稍后找到并删除它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 2016-08-05
      相关资源
      最近更新 更多