将 NSFetchRequest 重用于 Core Data 的多个不同提取有啥不好的吗?

Posted

技术标签:

【中文标题】将 NSFetchRequest 重用于 Core Data 的多个不同提取有啥不好的吗?【英文标题】:Is there anything bad about reusing an NSFetchRequest for several different fetches with Core Data?将 NSFetchRequest 重用于 Core Data 的多个不同提取有什么不好的吗? 【发布时间】:2012-05-20 13:52:26 【问题描述】:

我的问题: 将 NSFetchRequest 重复用于 Core Data 的多个不同提取有什么不好的吗?

示例代码:

NSFetchRequest *request = [[NSFetchRequest alloc] init];

NSEntityDescription *logEntity = [NSEntityDescription entityForName:@"LogEntry" inManagedObjectContext:context];
[request setEntity:logEntity];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"dateTimeAction" ascending:NO]; // ascending NO = start with latest date
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status == %@",@"op tijd"];
[request setPredicate:predicate];
[request setFetchLimit:50];

NSError *error = nil;
NSInteger onTimeCount = [context countForFetchRequest:request error:&error];

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"status == %@",@"uitgesteld"];
[request setPredicate:predicate1];
[request setFetchLimit:50];

NSInteger postponedCount = [context countForFetchRequest:request error:&error];

NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"status == %@",@"gemist"];
[request setPredicate:predicate2];
[request setFetchLimit:50];

NSInteger missedCount = [context countForFetchRequest:request error:&error];

【问题讨论】:

【参考方案1】:

这不是问题,但在给出的示例中它并没有给你带来太多好处(只是一些代码简洁。)创建提取请求最昂贵的部分是解析谓词格式字符串。

如果您提供的代码被频繁调用,并且您希望加快速度,可以尝试以下一些想法:

创建所有谓词并仅获取一次请求:可能在dispatch_once() 块中并静态存储它们;或在构造函数中并存储在对象字段中 不要指定排序描述符,因为如果您只关心计数,顺序并不重要 如果实际谓词比显示的更复杂或更灵活,请创建一个带有替换变量的通用模板谓词,并使用predicateWithSubstitutionVariables: 生成指定副本。 为了更简洁的代码,使用模型编辑器在对象模型中定义该模板,并使用fetchRequestFromTemplateWithName:substitutionVariables: 创建获取请求。

如果你愿意,我可以编写一些示例代码。

【讨论】:

需要排序描述符结合[request setFetchLimit:50];获取最新的50个元素。我想我可以为所有请求设置一次 fetchLimit。 啊。然后,如果您稍后重用 FR 来获取实际的日志条目,并且只是如图所示对它们进行计数,我建议仅在对象获取期间设置排序描述符,并在计数获取期间设置回 nil。如果超过 50 个,则无论“哪个”计数,count fetch 都将返回 50。【参考方案2】:

我认为这不是问题,因为NSFetchedRequest 只是一个搜索条件描述符,而且您可以在获取的请求上拥有多个谓词,如下所示:

NSPredicate *predicates = [NSCompoundPredicate andPredicateWithSubpredicates:NSArray_of_predicates];

【讨论】:

【参考方案3】:

如果您在同一商店或不同商店使用相同型号重复使用它们也没关系。在使用相同的提取请求查询具有不同模型的多个商店时,我遇到了崩溃(例如在 NSKnownKeysDictionary1 中)。重用请求似乎很有意义,因为我只是从两个不同的地方获取同一个实体。实体名称和谓词相同。您会认为这没问题,因为 fetch 请求采用实体名称而不是实体描述;后者将是不同商店/模型中同一实体的不同(但等效)对象。但是,获取请求似乎缓存了实体描述,并且没有检查它对于当前执行它的上下文是否仍然有效。

但是,您可以在多个 fetch 请求中重用相同的谓词而不会出现问题。

【讨论】:

以上是关于将 NSFetchRequest 重用于 Core Data 的多个不同提取有啥不好的吗?的主要内容,如果未能解决你的问题,请参考以下文章

Swift Core Data NSFetchRequest 没有结果

如何在类方法中执行 Core Data NSFetchRequest?

NSFetchRequest 用于行中的子对象

NSPredicate 用于 NSFetchRequest 中的多个匹配项

NSFetchRequest 不适用于谓词

从 Core Data 中获取随机对象