关于我正在做的事情的一些背景:
我从包含许多小工具数据的服务器下载CSV文件。然后使用CSV解析器将数据解析为NSDictionaries数组。完成后,下面的代码将字典中保存的信息写入核心数据。
快速解释下面代码的作用:
第一次应用程序执行此操作时,它工作正常(即必须为每个创建所有新小工具和下载手册)。如果我更新服务器上的小工具手册并再次运行应用程序,我会收到错误(我在代码中标记了该行):
非法尝试在不同上下文中的对象之间建立关系'theGadget'
实体都是在同一个MOC上创建的,所以我不确定为什么会出现错误。无论如何,我从here开始相信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]);
}
}
提前致谢!!
答案 0 :(得分:0)
更新现有数据时,我的解决方法是获取与小工具关联的现有手动实体并覆盖其数据,而不是删除手动实体并重新创建。
这不是一个真正的解决方案,所以如果你已经知道上面的代码有什么问题,请告诉我!