我希望这不是一个重复的问题。我似乎找不到类似的东西。大多数核心数据问题似乎都与新对象的创建有关……
我有一个包含大约 23,000 个项目的数据库的程序。我正在尝试创建一个导出/导入功能以将数据发送到其他设备(未与 iCloud 链接)。
导出工作正常,电子邮件也是如此......
我有导入功能,但它运行缓慢(稍后会详细介绍,似乎不适用于 iPhone 5 或 iPad 3)
我有一个函数可以解析导入到 NSArray (_importedRows) 中的数据,然后运行以下代码:
self.managedObjectContext = [(AppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSManagedObjectContext *ctx = self.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"CHECKLIST"
inManagedObjectContext:ctx];
[fetchRequest setEntity:entity];
ImportedData *importedData;
NSString *verify;
NSError *error = nil;
NSManagedObject *updatedObject;
NSArray *matchingItems;
for (int i = 0; i < [_importedRows count]; i++) {
importedData = [_importedRows objectAtIndex:i];
verify = importedData.uniqueID;
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"uniqueID == %@", verify]];
[fetchRequest setFetchLimit:1];
matchingItems = [ctx executeFetchRequest:fetchRequest error:&error];
for (updatedObject in matchingItems) {
HUD.detailsLabelText = [NSString stringWithFormat:@"Updating %@" , [updatedObject valueForKey:@"figureName"]];
[updatedObject setValue:importedData.numberOwned forKey:@"numberOwned"];
[updatedObject setValue:importedData.numberWanted forKey:@"wishList"];
[updatedObject setValue:importedData.availableTrade forKey:@"tradeList"];
}
[ctx save:&error];
if (error != nil) {
NSLog(@"error saving managed object context: %@", error);
}
}
基本上,我正在抓取一个核心数据实体,然后循环遍历我的数组以检查匹配项。当我找到匹配项(uniqueID 谓词)时,我正在使用导入的数据更新对象。此代码在我的 iPhone 4s 上运行良好,但速度较慢。4,000 个项目大约需要 4-5 分钟。我做错了什么公然错误吗?我应该更频繁地调用保存功能吗?
作为奖励,由于某种原因,当我在 iPhone 5 上测试它时,这段代码几乎永远不会工作。10 次中有 9 次(在我的 iPad 3 上 50% 的时间)我得到一个
“1 月 14 日 08:06:44:*由于未捕获的异常 'NSInvalidArgumentException' 导致应用程序终止,原因:'-[__NSCFSet addObject:]: 尝试插入 nil'”
在控制台中。想法?
如果需要更多详细信息,请告诉我!
更新:似乎handleOpenURL被调用了两次......一次在applicationdidfinishlaunching中
NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
if (url != nil && [url isFileURL]) {
[self.window.rootViewController performSelector:@selector(showWithLabel:) withObject:url afterDelay:6];
}
一次在这里:
-(BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{ if (url != nil && [url isFileURL]) { [self.window.rootViewController performSelector:@selector(showWithLabel:) withObject:url]; } 返回是;}
我必须将这两个都放在应用程序委托中,否则函数不会总是被调用(一次是在应用程序启动时,如果应用程序已经在后台,我相信一次) - 我添加了一个检查以防止它在 showWithLabel 线程中第二次启动,但这似乎不是一个非常优雅的解决方案......
更新:@mundi 建议清理 fetchedresults 代码如下:
NSArray *importedIDs = [_importedRows valueForKeyPath:@"uniqueID"];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
fetchRequest.entity = [NSEntityDescription entityForName:@"CHECKLIST"
inManagedObjectContext:ctx];
fetchRequest.predicate = [NSPredicate predicateWithFormat:
@"uniqueID in %@", importedIDs];
NSError *error = nil;
NSManagedObject *updatedObject;
NSArray *matchingItems;
matchingItems = [ctx executeFetchRequest:fetchRequest error:&error];
ImportedData *importedData;
for (int i = 0; i < [_importedRows count]; i++) {
importedData = [_importedRows objectAtIndex:i];
for (updatedObject in matchingItems) {
if ([importedData.uniqueID isEqualToString:[updatedObject valueForKey:@"uniqueID"]]) {
HUD.detailsLabelText = [NSString stringWithFormat:@"Updating %@" , [updatedObject valueForKey:@"figureName"]];
[updatedObject setValue:importedData.numberOwned forKey:@"numberOwned"];
[updatedObject setValue:importedData.numberWanted forKey:@"wishList"];
[updatedObject setValue:importedData.availableTrade forKey:@"tradeList"];
}
}
}
[ctx save:&error];
但组合的 fetchedresults 极大地提高了速度(最初 4000 个项目需要 240 秒,现在 80-120 秒之间)
首先对数组进行排序,然后按顺序更新再次大大加快了它的速度:
NSArray *matchingItemsSorted;
matchingItemsSorted = [matchingItems sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [a valueForKey:@"uniqueID"];
NSString *second = [b valueForKey:@"uniqueID"];
return [first caseInsensitiveCompare:second];
}];
NSArray *importedRowsSorted;
importedRowsSorted = [_importedRows sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [a valueForKeyPath:@"uniqueID"];
NSString *second = [b valueForKeyPath:@"uniqueID"];
return [first caseInsensitiveCompare:second];
}];
int i = 0;
for (updatedObject in matchingItemsSorted) {
NSLog(@"do we match? %@ : %@", [[importedRowsSorted objectAtIndex:i] valueForKeyPath:@"uniqueID"], [updatedObject valueForKey:@"uniqueID"]);
HUD.detailsLabelText = [NSString stringWithFormat:@"Updating %@" , [updatedObject valueForKey:@"figureName"]];
[updatedObject setValue:[[importedRowsSorted objectAtIndex:i] valueForKeyPath:@"numberOwned"] forKey:@"numberOwned"];
[updatedObject setValue:[[importedRowsSorted objectAtIndex:i] valueForKeyPath:@"numberWanted"] forKey:@"wishList"];
[updatedObject setValue:[[importedRowsSorted objectAtIndex:i] valueForKeyPath:@"availableTrade"] forKey:@"tradeList"];
i++;
}
有 nslog 的 4000 个项目需要 13 秒左右......现在唯一奇怪的是,当我注释掉 nslog 时,它经常崩溃......它发生得如此之快以至于破坏了核心数据 - 当它不崩溃时,只需要大约 4 秒?
谢谢,扎克