12

我想要一份关于两者比较的完整清单。我知道的事情:

executeFetchRequest

  • 发送到 MOC 的消息
  • 返回一个托管对象数组
  • 目标:从持久存储中获取对象到 MOC
  • 与表视图:与表视图无关
  • 频率:经常在循环中使用,因此可以被多次调用

performFetch

  • 发送到 FRC 的消息
  • 调用后,用于fetchedObjects返回托管对象数组
  • 使用表视图:FRC 专门用于保持托管对象和表视图行同步,并用于performFetch初始化该过程。
  • 频率:通常只有一次。除非 FRC 的 fetch 请求发生变化,否则不需要performFetch第二次 调用

如果我错了,请纠正我并附加列表。谢谢你。

4

2 回答 2

16

关于executeFetchRequest:

发送到 MOC 的消息

是的

返回一个托管对象数组

可以,但您也可以更改要检索的结果类型。在NSFetchRequest您可以设置不同的结果类型:

- (void)setResultType:(NSFetchRequestResultType)type

whereNSFetchRequestResultType可以是不同的类型。取自苹果文档:

enum {
   NSManagedObjectResultType        = 0x00,
   NSManagedObjectIDResultType      = 0x01,
   NSDictionaryResultType           = 0x02
   NSCountResultType                = 0x04
};
typedef NSUInteger NSFetchRequestResultType; 

目标:从持久存储中获取对象到 MOC

是的,创建NSFetchRequest并执行请求,它与在 SQL 中创建 SELECT 语句相同。如果您还使用 aNSPredicate它与使用 SELECT-WHERE 语句相同。

与表视图:与表视图无关

是的,但是您可以使用检索到的数据填充表格

频率:经常在循环中使用,因此可以被多次调用

这取决于您想要实现的目标。它可能在一个循环内,也可能不在一个循环内。在循环中执行请求可能会影响性能,但我不会担心。在引擎盖下,Core Data 维护着一种缓存机制。每次执行请求时,如果数据不在缓存中,Core Data 会在您的存储(例如 sql 文件)上执行一次往返,并用它检索到的对象填充缓存。如果执行相同的查询,由于缓存机制,往返不会再次执行。无论如何,您可以避免在运行循环中执行请求,只需将该请求移出循环即可。

关于performFetch:

发送到 FRC 的消息

是的

调用后,使用 fetchedObjects 返回一个托管对象数组

[_fetchedResultsController objectAtIndexPath:indexPath];是的,但是如果您要填充表格中的特定单元格,您也可以检索对象。

在这里,我真的建议阅读关于NSFetchedResultsController的不错的教程

使用表视图:FRC 专门用于保持托管对象和表视图行同步,并使用 performFetch 来初始化该过程。

是的,aNSFetchedResultsController与 a NSManagedObjectContextfor you 结合使用。此外,它还支持延迟加载数据。假设您检索了 1000 个元素,并且希望将它们显示在UITableView. 设置一个NSFetchRequest类似的请求:

[fetchRequest setFetchBatchSize:20];

并将它与 a 的实例一起使用NSFetchedResultsController,它首先允许加载 20 个元素。然后当您滚动时,会加载其他 20 个元素,依此类推。如果没有,NSFetchedResultsController您必须手动实现此行为。请参阅我提供的教程以获取更多信息。

频率:通常只有一次。除非 FRC 的 fetch 请求发生变化,否则无需再次调用 performFetch

这取决于您想要达到的目标。大多数时候你可以调用一次。

希望有帮助。

编辑

您必须performFetch明确调用。我喜欢NSFetchedResultsController在我的头文件(.h)中创建一个属性,比如

@property (nonatomic, strong, readonly) NSFetchedResultsController* fetchedResultsController;

并在你的实现文件(.m)中合成它,比如

@synthesize fetchedResultsController = _fetchedResultsController;

然后总是在 .m 文件中覆盖 getter 以创建它的新实例:

- (NSFetchedResultsController*)fetchedResultsController
{
    // it already exists, so return it
    if(_fetchedResultsController) return _fetchedResultsController;

    // else create it and return

    _fetchedResultsController = // alloc-init here with complete setup

   return _fetchedResultsController;
}

完成后,在您的课程中(例如在viewDidLoad方法中)使用它

NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {

    // Handle the error appropriately.
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
于 2012-09-29T13:16:39.443 回答
4

您正在比较错误的元素。NSFetchedResultsController使用NSManagedObjectContext来执行获取,并在适当的配置下,监视托管对象上下文中的更改以验证它正在监视的获取属性的状态,但实际的获取是由上下文完成的。在这两种情况下,NSManagedObjectContext都进行提取。不同之处在于,NSManagedObjectContext直接使用,您将获得一个 NSArray 类型的对象(实际的运行时类与您使用的数组不同[NSArray array]),同时NSFetchedResultsController具有不同的目的(拥有结果集合并监视对记录和实体的更改在其获取请求上)。换句话说,NSFetchedResultsController使用上下文工作,但它的工作方式与简单的对象集合不同。

一个观察:你不应该executeFetchRequest在循环中使用,特别是称之为“很多次”。每个提取都有其性能成本。您可以调用executeFetchRequest一次,然后循环检查结果。

于 2012-09-28T18:58:04.943 回答