0

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

到目前为止,这是我正在做的事情:

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

在合并期间,将步骤 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.  
    }
}

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

我觉得这是我所缺少的一些简单的东西,并且可以在正确的方向上使用轻推。

4

3 回答 3

1

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

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

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

更新

有几种方法可以做到这一点,但它们需要您进行一些实验。我会首先尝试“触摸”获取的对象的想法。也许更新“lastAccessed”日期或其他内容,以便这些对象将合并作为“更新”。我怀疑这是最简单的路径。

除此之外,另一种选择是将这些对象的通知广播回主线程​​(使用它们NSManagedObjectID作为跨线程边界的载体),以便您可以手动更新它们;然而,这并不理想。

于 2010-04-07T16:12:39.523 回答
0

嘿贾斯汀,你fetchLimit会造成这个吗?

对数据库中最近 100 个结果的NSFetchedRequestController初始化查询(使用 setFetchLimit:)。即使有 1000 行,我也只希望一开始可以访问 100 行。

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

有没有开启排序?如果是这样,一些插入的托管对象可能会显示出来,因为它们会因结果的排序而取代现有的 100 个对象。

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

我也尝试了 fetchLimit 方法,这也很有效。您不需要删除和重建NSFetchedResultsController,您只需调整 fetchRequest 的 fetchLimit:

tableMaxItems += 100;
[myFRC.fetchRequest setFetchLimit:tableMaxItems];
于 2010-04-09T04:33:02.697 回答
0

这是我最终解决此问题的方法。在合并来自我NSOperation的 MOC 的更改之前,我遍历存储在其中的值NSUpdatedObjectsKey并使用 willAccessValueForKey 触摸它们。为了让它们成为关键,我接受了 Marcus 上面的建议,并添加了一个 lastAccessed 属性,如果对象已经存在于持久存储中NSUpdatedObjects,我将其设置为当前日期。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];
}
于 2010-04-12T15:09:13.247 回答