我在(核心数据)实体中保存了我的tableviewdata的最新Internet请求,但是有关于“fault”的错误异常有问题。 我有两个方法'loadData',它获取将在我的tableview和'loadThumbnails'中加载的最新'ordersitems',它将尝试将缩略图缓存到核心数据实体中。 当托管对象被删除且缩略图方法仍尝试访问它时,会发生此问题。虽然我做了一个变量stopThumbnails来停止loadThumbnails方法,但问题仍然存在。
什么是适当的iOS 6方式来延迟加载图像并将它们保存到coredata但检查对象是否尚未删除?我发现这个Core Data multi thread application很有用,但我对核心数据的新手理解仍然有限,我在编写代码时遇到了问题。我阅读了有关http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/coredata/Articles/cdConcurrency.html的苹果文档,但很难完全理解。
我希望至少我的http请求加载不同步(但最好尽可能多)我想出了以下内容:
-(void)viewdidload
{
NSFetchRequest *fetchReq = [NSFetchRequest fetchRequestWithEntityName:@"OrderItems"];
fetchReq.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
self.data = [self.managedObjectContext executeFetchRequest:fetchReq error:nil];
MYFILTER = @"filter=companyX";
[self loadData];
}
-(void)loadData
{
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//json request from url
NSDictionary *reqData = myOrderJSONRequest(MYFILTER);
dispatch_async( dispatch_get_main_queue(), ^{
if(reqData!=NULL && reqData!=nil)
{
//request successful so delete all items from entity before inserting new ones
stopThumbnails = YES;
for(int i=self.data.count-1;i>=0;i--)
{
[self.managedObjectContext deleteObject:[self.data objectAtIndex:i]];
}
[self.managedObjectContext save:nil];
if(reqData.count>0)
{
//insert latest updates
for (NSDictionary *row in reqData){
OrderItem *item = [NSEntityDescription insertNewObjectForEntityForName:@"OrderItem" inManagedObjectContext:self.managedObjectContext];
item.order_id = [NSNumber numberWithInt:[[row objectForKey:@"order_id"] intValue]];
item.description = [row objectForKey:@"description"];
item.thumbnail_url = [row objectForKey:@"thumbnail_url"];
}
[self.managedObjectContext save:nil];
}
NSFetchRequest *fetchReq = [NSFetchRequest fetchRequestWithEntityName:@"OrderItems"];
fetchReq.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
self.data = [self.managedObjectContext executeFetchRequest:fetchReq error:nil];
[TableView reloadData];
//LOAD THUMBNAILS ASYNCHRONOUS
stopThumbnails = NO;
[self loadThumbnails];
}
else{
//NO INTERNET
}
});
});
}
-(void)loadThumbnails
{
if(!loadingThumbnails)
{
loadingThumbnails = YES;
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i=0;i<self.data.count; i++) {
if(!stopThumbnails)
{
OrderItem *item = [self.data objectAtIndex:i];
if(item.thumbnail==NULL)
{
//ASYNCHRONOUS IMAGE REQUEST
NSURL *image_url = [NSURL URLWithString:item.thumbnail_url];
NSData *image_data = [NSData dataWithContentsOfURL:image_url];
dispatch_async( dispatch_get_main_queue(), ^{
if(image_data!=nil && image_data!=NULL && !stopThumbnails)
{
//IMAGE REQUEST SUCCESSFUL
item.thumbnail = image_data;
[self.managedObjectContext save:nil];
//RELOAD AFFECTED TABLEVIEWCELL
NSIndexPath* rowToReload = [NSIndexPath indexPathForRow:i inSection:0];
NSArray* rowsToReload = [NSArray arrayWithObjects:rowToReload, nil];
[TableView reloadRowsAtIndexPaths:rowsToReload withRowAnimation:UITableViewRowAnimationFade];
}
else
{
loadingThumbnails = NO;
return;
}
});
}
if(stopThumbnails)
{
dispatch_async( dispatch_get_main_queue(), ^{
loadingThumbnails = NO;
return;
});
}
}
else{
dispatch_async( dispatch_get_main_queue(), ^{
loadingThumbnails = NO;
return;
});
}
}
dispatch_async( dispatch_get_main_queue(), ^{
loadingThumbnails = NO;
return;
});
});
}
}
当然,非常感谢任何帮助:)
答案 0 :(得分:0)
嗯,我不知道这是否是正确的方法,但它有效,所以我会将此标记为答案。
要在后台执行所有操作,我使用了第二个nsmanagedobjectcontext(MOC),然后将更改合并到主MOC。虽然我必须使用NSManagedObjectContextDidSaveNotification来合并两个上下文的更改,但调度队列工作得很好。
因为IOS 5可以使用块而不是为你做合并。所以我决定使用它而不是调度方式(这样我就不必使用通知)。
同样使用块我在后台队列中选择了一个对象而在另一个队列上被删除时遇到了同样的问题(故障)。所以我决定不立即删除它,为OrderItem插入一个NSDate'deleted'属性。然后有一个带有删除检查的计时器,以查看是否有超过10分钟前删除的对象。这样我确定没有缩略图仍在下载。有用。虽然我仍然想知道id这是正确的方法:)