在查找或创建循环期间将数据附加到NSFetchedResultsController

时间:2010-04-07 05:16:31

标签: cocoa core-data nsfetchedresultscontroller

我有一个由NSFetchedResultsController管理的表视图。但是,我遇到了查找或创建操作的问题。当用户点击表格视图的底部时,我正在查询我的服务器以获取另一批内容。如果它不存在于本地缓存中,我们创建它并存储它。但是,如果确实存在,我想将该数据附加到获取的结果控制器并显示它。我不太清楚这一部分。

这是我到目前为止所做的事情:

  1. NSFetchedRequestController在初始化查询数据库中的最新100个结果时(使用setFetchLimit:)。即使有1000行,我也只想要100个可访问的行。
  2. 将返回的值数组从我的服务器传递给NSOperation进行处理。
  3. 在操作中,创建一个新的托管对象上下文以便使用。
  4. 在操作中,我遍历数组并执行获取请求以查看对象是否存在(基于其服务器ID)。
  5. 如果对象不存在,我们创建它并将其插入到操作的托管对象上下文中。
  6. 迭代完成后,我们保存托管对象上下文,这会在我的主线程上触发合并通知。
  7. 在合并期间,将步骤4中新创建的对象插入到表中,但任何已存在且刚刚获取的对象都不会。这是我的NSOperation的相关代码

    for (NSDictionary *resultsDict in self.results)
    {
        NSNumber *dbID = [NSNumber numberWithLong:[[resultsDict valueForKey:@"id"] longValue]];
    
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        [fetchRequest setEntity:[NSEntityDescription entityForName:kResultEntityName inManagedObjectContext:moc]];
        [fetchRequest setPredicate:[NSPredicate predicateWithFormat: @"(dbID == %@)", dbID]];
    
        NSError *error = nil;
    
        NSManagedObject *newObject = nil;
        // Query the data store to see if the object exists
        newObject = [[moc executeFetchRequest:fetchRequest error:&error] lastObject];
        [fetchRequest release];
    
        // If it doesn't exist, create it.
        if ((tweet == nil))
        {
            // Create the NSManagedObject and insert it into the MOC.  
        }
    }
    

    我想传递给主线程的是新创建的对象以及每次循环迭代时可能在获取请求中获取的任何现有对象。

    我觉得这很简单,我很想念,并且可以在正确的方向上轻推。

3 个答案:

答案 0 :(得分:1)

  

此时,之前未在我的Core Data存储中本地缓存的任何对象都会出现,但之前存在的对象不会出现。

你能解释一下吗?我不确定你以前存在的是什么意思。它是否与您现在在检索后执行的表上的过滤器不匹配,或者您是说先前的对象从表中消失了?

另外,您如何实现NSFetchedResultsController的委托方法?您是在进行简单的表重新加载还是插入/移动行?

更新

有几种方法可以做到这一点,但他们需要您进行一些实验。我首先想要“触摸”所取出的物体。也许更新'lastAccessed'日期或某些东西,以便这些对象将合并为“更新”。我怀疑这是最简单的方法。

Baring,另一个选择是将这些对象的通知广播回主线程​​(使用他们的NSManagedObjectID作为跨越线程边界的载体),以便您可以手动更新它们;但这不太理想。

答案 1 :(得分:0)

嘿贾斯汀,你的fetchLimit可能造成这种情况吗?

  

NSFetchedRequestController时   初始化查询最新的100   数据库的结果(使用   setFetchLimit:)。即使有   1000行,我只想要100个可访问   起初。

无论您插入了多少个管理对象,NSFetchedResultsController仍然会有100个结果的限制。合并。

您是否打开了排序?如果是这样,一些插入的托管对象可能会显示,因为它们取代了现有的100个,这是由于结果的排序。

我在获取结果的“页面”方面遇到了同样的问题,并且在我的提取中使用了下限约束(使用NSComparisonPredicate中的sorted属性)并使用最后一项进行调整在最近的“页面”结果中。

我也尝试了fetchLimit方法,这也有效。你不需要删除&重建NSFetchedResultsController,你可以调整fetchRequest的fetchLimit:

tableMaxItems += 100;
[myFRC.fetchRequest setFetchLimit:tableMaxItems];

答案 2 :(得分:0)

以下是我最终解决这个问题的方法。在合并来自NSOperation的MOC的更改之前,我遍历NSUpdatedObjectsKey中存储的值并使用willAccessValueForKey触摸它们。为了让他们进入NSUpdatedObjects密钥,我上面提到了Marcus的建议并添加了一个lastAccessed属性,如果该对象已存在于持久存储中,我将其设置为NSOperation中的当前日期。

- (void)mergeChanges:(NSNotification *)notification
{
  NSAssert([NSThread mainThread], @"Not on the main thread");  
  NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];

  for (NSManagedObject *object in updatedObjects)
  {
    [[managedObjectContext objectWithID:[object objectID]] willAccessValueForKey:nil];
  }

  [managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}