【问题标题】:iOS Core Data - Updating Multiple recordsiOS 核心数据 - 更新多条记录
【发布时间】:2013-02-15 08:29:02
【问题描述】:

我已经搜索过,但仍然没有找到任何非常有效的方法。问题/答案太老了,或者根本不适合我。这是我第一次尝试“我自己的”应用程序。由于这似乎是一种通行权,我正在制作一个清单应用程序。这就是我要找的东西:

我的数据存储包含 4 个属性:name, category, isChecked, isActive(随着我的扩展,肯定会有更多属性)

当我的视图控制器最初加载时,NSFetchedResultsController 有一个NSPredicate,它只检索属性isActive 为YES(或[NSNumber numberWithBool:YES)的记录。然后它获取这些记录并将它们显示到用户的适当单元格中。当用户单击单元格时,Data Store 会相应地更新并更改 isChecked 属性。到目前为止一切正常。

我现在需要做的是能够从列表中删除项目(1 个或更多)。具体来说,我需要它将数据存储属性isCheckedisActive 更新为NO,前提是它的当前isChecked 属性为YES。 (我不打算从数据存储中删除记录,因为它们将用于构建数据库以供用户将来使用。)

我用过,除其他外:

[[[self fetchedResultsController] fetchedObjects] 
   setValue:[NSNumber numberWithBool:NO] 
   forKey:@"isChecked"];

这确实有效,它会删除复选标记并相应地更新商店。问题是,我不仅对isActive 项目的数据存储发出另一个请求,它还搜索获取的整个“活动列表”并将它们的每个isChecked 属性设置为NO。对于小型列表来说,这可能不是什么大问题,但随着列表的扩展,这可能是个问题。

另一个问题是,如果我添加:

[[[self fetchedResultsController] fetchedObjects] 
   setValue:[NSNumber numberWithBool:NO] 
   forKey:@"isActive"];

它将我的所有列表项设置为 NO(以及同一方法中的第二个数据存储请求。)

所以我的问题是:我如何才能通过列表,仅查找已检查的项目并仅更新那些isChecked 属性为 YES 的记录(设置 isChecked && isActive 属性 = NO)而不是通过整个列表?

我已经尝试为这个按钮操作专门创建一个单独的 fetchedResultsController,它确实有效(也就是说,它没有崩溃)但是调试器弹出了一个相当大的“严重应用程序错误”。我不会发布错误消息,因为它很长并且很可能与任何解决方案无关。

任何帮助将不胜感激。在此先感谢,请保持温柔:-]。

编辑

我尝试使用 for 循环 for (NSString *item in fetchedResultsController) 但我收到错误 ...may not respond to 'countByEnumeratingWithState:objects:count'

这里似乎需要某种循环,但同样,我找不到任何相关或过时的东西。再次感谢您的帮助。

编辑 2

这是我在为此按钮/方法运行第二个单独的 fetchRequestController 时遇到的原始错误:

An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (4), plus or minus the number of rows inserted or deleted from that section (0 inserted, 3 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)

【问题讨论】:

标签: iphone xcode sqlite ios6 xcode4.5


【解决方案1】:

您可以遍历 fetchedObjects 集合并更改托管对象。更改它们后,您需要重新加载列表(我猜您使用的是 tableview)。

我不知道你的类被命名为什么,但一般来说,你可以遍历托管对象的集合并更改它们。请记住,如果您想在应用关闭时保留这些更改,则需要保存托管对象上下文。

NSArray* myCollection = [[self fetchedResultsController] fetchedObjects];
for(ActiveListData *managedObject in myCollection)
{
    if(managedObject != nil && managedObject.isChecked)
    {
        managedObject.isChecked = NO;
        managedObject.isActive = NO;
    }
}

如果您想检查数据库中的所有对象,您需要在 NSFetchedResultsController 中使用一个新方法,该方法对 isChecked 进行谓词检查,然后循环并编辑结果集合。

您可能想发布您的错误代码,因为我们可以指出您做错了什么。

编辑:如果您不熟悉使用 Core Data,Apple 文档提供了大量信息:http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/Articles/cdBasics.html

【讨论】:

  • 我尝试了这个,使用 ActiveListData 这是我的 NSManaged 子类的名称,但得到错误`在核心数据更改处理期间捕获了异常。这通常是 NSManagedObjectContextObjecsDidChangeNotification 观察者中的一个错误。索引 0 的部分中索引 3 处没有对象,用户信息 (null)。检查我上面的编辑,看看我为此创建单独的“fetchRequestController”时遇到的原始错误。
  • 是的,我查看了苹果开发文档,有大量信息,但要找到一个实际的例子(如果有的话)需要大量的理论。至少在这里,我可以把我需要的东西放到一个上下文中,并得到一个相对直接的答案。我尽我所能阅读了开发文档,但这并不总是最容易找到答案的地方
  • fetchedObjects 返回什么?是 NSArray 吗?
  • 是的,我相信这就是该函数的用途,将每个对象从 NSFerchedResultsController 中拉出,这样您就可以遍历它们
  • 只需将 fetchedObjects 保存在 NSArray 中,并在需要更改它们时循环遍历数组。确保将它们转换为 ActiveListData。
【解决方案2】:

感谢@ggfela 的回答。他的回答过程很到位。这是我放入按钮/方法中的实际代码,希望将来能帮助其他人:

NSArray *moc = [[self fetchedResultsController] fetchedObjects];

for  (ActiveListData *item in moc) {
    if (item != nil && item.isChecked.boolValue == 1) {
        item.isChecked = [NSNumber numberWithBool:NO];
        item.isActive = [NSNumber numberWithBool:NO];
    }
}

// Call to Data Store to update the list
NSError *error;
if (![self.managedObjectContext save:&error]) {
    FATAL_CORE_DATA_ERROR(error);
    return;

说明:

将调用fetchedResultsController方法的结果内容加载到名为moc的临时变量中

使用for 循环循环遍历moc 的数组。 ActiveListData 是我为我的核心数据创建的 NSManagedObject 子类,是从数据存储中插入分隔值/属性的合适位置。从那里开始,这很简单,我确保 item 不是 nil 并且该项目的属性是我需要的值。

注意

Core Data 不存储布尔值 YES 和 NO,而是分别存储 1 和 0,但是当您调用或比较这些值时,您根本无法比较 item.isChecked 的值,因为它被传回给您一个布尔值而不是整数。您也不能简单地比较item.isChecked == YES,因为isChecked@propertyNSNumber。所以,在if 的情况下,我输入item.isChecked.boolValue,因为这会给我代表它的布尔值的整数,在这种情况下,我让它检查1(是)。 (对不起,如果我的解释是错误的和/或令人困惑的,但这是我理解它的方式,也是此代码工作的唯一方式。)

然后,设置这些属性的新值就像设置任何其他变量时所期望的一样。唯一的“棘手”区别是 NSManagedObject 子类将isCheckedisActive@property 设置为NSNumber(如前所述),因此为了将正确的值发送回Core Data,您使用NSNumber类的方法numberWithBool

如果有人对我的FATAL_CORE_DATA_ERROR(error) 调用感到困惑,这只是在Prefix.pch 文件中定义的一个宏,用于处理来自 managedObjectContext 的错误。您可以使用您选择的任何(或不使用)错误处理。

再次感谢@ggfela 的帮助!!如果其他人对如何应用此代码有任何其他建议,请告诉我!

【讨论】:

  • 干得好,我完全忘记了 CoreData 使用 NSNumbers 而不是布尔值。
【解决方案3】:
猜你喜欢
  • 2012-07-02
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多