1

我正在做的一些背景:

我从服务器下载了一个 CSV 文件,其中包含许多小工具的数据。然后使用 CSV 解析器将数据解析为 NSDictionaries 数组。完成后,下面的代码会将字典中保存的信息写入核心数据。

下面的代码在做什么的快速解释:

  • 获取所有现有的核心数据项
  • 对于每个字典,检查产品代码是否与核心数据中已经存在的代码匹配
  • 如果没有匹配,创建一个新的小工具实体并保存它的数据
  • 如果有匹配项,请使用最新信息进行更新
  • 如果小工具是新的或现有手册已过期,请使用 AFNetworking 下载小工具的用户手册(zip 文件)。手册被创建为一个与小工具有关系的单独实体(我已经这样做了,以防需要保存多个手册)。

应用程序第一次执行它时运行良好(即它必须创建所有新的小工具并为每个小工具下载手册)。如果我在服务器上更新小工具的手册并再次运行该应用程序,则会收到错误消息(我已在代码中标记了该行):

非法尝试在不同上下文中的对象之间建立关系“theGadget”

这些实体都是在同一个 MOC 上创建的,所以我不确定为什么会出现错误。无论如何,我从这里开始相信AFNetworking 的回调在主线程上,所以我可以使用一个 MOC。也许我犯了另一个错误,或者有更好的方法来做我想做的事情......?

-(void)populateCoreDataWithServerData {

    // Fetch all the existing info from core data
    theItems = [self loadFromDatabase:@"Gadgets" andSortDescriptor:nil];

    int row = 0;

    // Cycle through each entry in the parsed CSV data.
    for (NSDictionary *itemDictionary in theItemsInCSV) {

        // Check to see if we've downloaded this item previously.
        Gadgets *gadget;
        bool foundIt = FALSE;
        bool needToUpdateZip = TRUE;

        for (int i = 0; i < [theItems count]; ++i) {

            // Check if we have downloaded it already. If so, update as the item in core data with any new data.
            if ([[[theItems objectAtIndex:i] productCode] isEqualToString:[itemDictionary objectForKey:@"Product Code"]]) {

                foundIt = TRUE;
                gadget = [theItems objectAtIndex:i];

                NSLog(@"Found this item in the local database. Won't be downloading it again.");

                // Check if the zip file with the instruction manual needs updating.
                if ([[[theItems objectAtIndex:i] zipURL] isEqualToString:[itemDictionary objectForKey:@"Manual Zip"]]) {
                    NSLog(@"The zip file is the same or non-existant, no need to update.");
                    needToUpdateZip = FALSE;
                }
                else {
                    NSLog(@"The zip file is different. Will download");
                }
            }
        }

        // If we haven't downloaded it before, create a new item. We'll update the fields in that.
        if (foundIt == FALSE) {
            gadget = (Gadgets *)[NSEntityDescription insertNewObjectForEntityForName:@"Gadget" inManagedObjectContext:self.managedObjectContext];
            NSLog(@"Didn't find this item in the local database. Had better download it.");
        }

        // Update all the fields.
        [gadget setName:[itemDictionary objectForKey:@"gadget name"]];
        //Set some more attributes (product code etc)


        // Download gadget manual (zip file) if it exists
        if (needToUpdateZip == TRUE) {  // Check if there's a URL in there

            // Create a temp folder
            if (![[NSFileManager defaultManager] fileExistsAtPath:[self tempDirectory]) {  // Use Formidible Key as in identifier rather than the Product Code as the Form Key never has any spaces in it.

                NSError* error;
                if([[NSFileManager defaultManager] createDirectoryAtPath:[self tempDirectory] withIntermediateDirectories:YES attributes:nil error:&error]) {
                    NSLog(@"Directory created");
                }
            }

            NSString *fileName = [[NSString alloc] initWithFormat:@"Temp%i.zip", row];
            NSString *fileNameWithPath = [[self tempDirectory] stringByAppendingPathComponent:fileName];

            // Download the zip
            NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[itemDictionary objectForKey:@"Manual Zip"]]];
            AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

            operation.outputStream = [NSOutputStream outputStreamToFileAtPath:fileNameWithPath append:NO];

            [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
                NSLog(@"Successfully downloaded file to %@", [self tempDirectory]);

                // Save the individual files to core data.
                Manuals *manual = (ARData *)[NSEntityDescription insertNewObjectForEntityForName:@"Manuals" inManagedObjectContext:self.managedObjectContext];
                [manual setTheGadget:gadget];  // ERROR APPEARS HERE  **********************************
                // Extract the zip file and set some attributes
            }
             failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                 NSLog(@"Download didn't work. Error: %@", error);
                 }
             ];

            [operation start];
        }

        ++row;
    }

    NSError *error;
    if (![managedObjectContext save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error localizedDescription]);
    }
}

提前致谢!!

4

1 回答 1

0

在更新现有数据时,我的解决方法是获取与小工具关联的现有手动实体并覆盖其数据,而不是删除手动实体并重新创建。

这不是真正的解决方案,所以如果您知道上面的代码有什么问题,请告诉我!

于 2013-07-28T01:20:03.413 回答