是否有更高效的内存搜索核心数据数据库?

时间:2011-01-16 05:10:46

标签: cocoa core-data memory-management

我需要查看我的核心数据库中是否存在从具有唯一标识符的CSV文件中获取的对象,这是我认为适合此任务的代码:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity;
entity = 
[NSEntityDescription entityForName:@"ICD9"
            inManagedObjectContext:passedContext];
[fetchRequest setEntity:entity];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"uniqueID like %@", uniqueIdentifier];
[fetchRequest setPredicate:pred];
NSError *err;
NSArray* icd9s = [passedContext executeFetchRequest:fetchRequest error:&err];
[fetchRequest release];
if ([icd9s count] > 0) {
    for (int i = 0; i < [icd9s count]; i++) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
        NSString *name = [[icd9s objectAtIndex:i] valueForKey:@"uniqueID"];
        if ([name caseInsensitiveCompare:uniqueIdentifier] == NSOrderedSame && name != nil)
        {
            [pool release];
            return [icd9s objectAtIndex:i];
        }
        [pool release];
    }
}
return nil;

经过更彻底的测试后,似乎这个代码导致我正在编写的应用程序中出现大量泄漏(它在3GS上崩溃,然后通过1459项目将其降低20%)。我觉得这不是最有效的方法,对于更有效的内存方式有什么建议吗?提前谢谢!

2 个答案:

答案 0 :(得分:2)

  • 请勿在请求谓词中使用like运算符。使用=。那应该快得多。
  • 您可以使用[c]修饰符通过谓词指定搜索的不区分大小写。
  • 没有必要在循环的每次迭代中创建和销毁NSAutoreleasePool。事实上,根本不需要它。
  • 您无需在for()循环内进行任何检查。你复制了谓词的工作。

所以我会将你的代码更改为:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:...];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"uniqueID =[c] %@", uniqueIdentifier]];
NSError *err = nil;
NSArray *icd9s = [passedContext executeFetchRequest:fetchRequest error:&err];
[fetchRequest release];
if (error == nil && [icd9s count] > 0) {
  return [icd9s objectAtIndex:0]; //we know the uniqueID matches, because of the predicate
}
return nil;

答案 1 :(得分:1)

使用Instruments中的Leaks模板搜寻泄漏。修复它们后,您当前的代码可能会很好。泄漏甚至可能不是代码。

其他问题:

  • 使用fast enumeration将使数组(1)上的循环更快,(2)更容易阅读。
  • 不要将release发送到自动释放池。如果您将代码移植到垃圾收集的Cocoa,则池将不会执行任何操作。而是发送它drain;在保留释放Cocoa和Cocoa Touch中,这与release的工作方式相同,并且在垃圾收集的Cocoa中,它会占用垃圾收集器,垃圾收集器是GC-land中最接近排放池的等效物。
  • Don't repeat yourself.您目前在一个游泳池中有两条[pool release];行,这让每位经验丰富的Cocoa和Cocoa Touch程序员都非常担心。将测试结果存储在布尔变量中的名称上,然后在条件之前排空池,然后有条件地返回对象。
  • 注意变量类型。 -[NSArray count]返回,-[NSArray objectAtIndex:]需要NSUInteger,而不是int。尽量保持所有类型的匹配。 (切换到快速枚举当然会以不同的方式解决此问题的这个实例。)
  • 不要隐藏版本。我几乎指责你泄漏了获取请求,然后注意到你把它埋在了代码的中间。使您的版本突出显示,以便您不太可能意外添加冗余(即崩溃诱导)。