1

我希望这不是一个重复的问题。我似乎找不到类似的东西。大多数核心数据问题似乎都与新对象的创建有关……

我有一个包含大约 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 秒?

谢谢,扎克

4

1 回答 1

1

你有两个嵌套循环。使用此模式加快速度:

NSArray *importedIDs = [_importedRows valueForKeyPath:@"uniqueID"];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
fetchRequest.entity = [NSEntityDescription entityForName:@"CHECKLIST"
                                  inManagedObjectContext:ctx];
fetchRequest.predicate = [NSPredicate predicateWithFormat:
            @"uniqueID in %@", importedIDs];

像这样,您可以获取一个包含所有匹配项的数组。

于 2013-01-15T11:43:12.817 回答