我在coredata NSManagedObjectContextDidSaveNotification中运行谓词来过滤我感兴趣的相关对象。
- (void)didSaveNotficiation:(NSNotification*)notification
{
NSSet *objects = nil;
NSMutableSet *combinedSet = nil;
NSPredicate *predicate = nil;
NSDictionary *userInfo = [notification userInfo];
objects = [userInfo objectForKey:NSInsertedObjectsKey];
combinedSet = [NSMutableSet setWithSet:objects];
objects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
[combinedSet unionSet:objects];
objects = [[notification userInfo] objectForKey:NSDeletedObjectsKey];
[combinedSet unionSet:objects];
//THis is slow
predicate = [NSPredicate predicateWithFormat:@"entity.name == %@ && %K == %@",
[XXContact entityName], XXContactRelationship.user,self];
[combinedSet filterUsingPredicate:predicate];
if ([combinedSet count] == 0) {
return;
}
[self process];
/* This is much faster
[combinedSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
if ([obj isKindOfClass:[XXContact class]]) {
XXContact* contact = (XXContact*)obj;
if (contact.user == self) {
[self process];
*stop = YES;
}
}
}];
*/
}
应用启动时,通知可以被调用超过100次。 当我对应用程序进行概要分析时,似乎函数predicateWithFormat非常慢,占用了20%的cpu。甚至过滤都不是很慢。谓词本身的创建是如此缓慢。 如果我将其更改为使用enumerateObjectsUsingBlock,它会变得更快,但代码的可读性较差。
有没有人有解释?谢谢。
答案 0 :(得分:1)
由于以下几个原因,您无法使用当前谓词超过枚举过滤所实现的时间:
didSaveNotficiation :
combinedSet
中的所有对象都必须进行评估) 我相信您最好的选择是自己实施谓词
为了改进谓词的实现,我建议:
//1. change .name property to an Integer/Enum value
//2. make your predicate static and reduce the compose and parse needs:
//(If you must use %K in your predicate this would be much harder)
//NOT TESTED
static NSPredicate* p = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
p = [NSPredicate predicateWithFormat:@"entity.name == $ENAME AND user == $USEROBJECT"];
});
NSPredicate* currPredicate = [p predicateWithSubstitutionVariables:@{@"ENAME" : [XXContact entityName], @"USEROBJECT" : [self objectID]}];
[combinedSet filterUsingPredicate:currPredicate];
如您所见,如果您尝试提高可读性,则会受损。