0

我正在将我的 tableviewdata 的最新 Internet 请求保存在(核心数据)实体中,但遇到有关“故障”的错误异常的问题。我有两种方法“loadData”,它获取将在我的表格视图中加载的最新“ordersitems”和“loadThumbnails”,它将尝试将缩略图缓存到核心数据实体中。当托管对象被删除并且缩略图方法仍然尝试访问它时,就会出现问题。虽然我做了一个变量 stopThumbnails 来停止 loadThumbnails 方法,但问题一直在发生。

什么是延迟加载图像并将它们保存到 coredata 但检查对象是否未被删除的正确 iOS 6 方法?我发现这个Core Data 多线程应用程序很有用,但我新手对核心数据的理解仍然有限,而且我在编写代码时遇到问题。我阅读了有关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;
        });
    });
}
}

任何帮助当然都非常感谢:)

4

1 回答 1

0

好吧,我不知道这是否是正确的方法,但它有效,所以我将其标记为答案。

为了在后台做所有事情,我使用了第二个 nsmanagedobjectcontext (MOC),然后将更改合并到主 MOC。调度队列工作得很好,虽然我不得不使用 NSManagedObjectContextDidSaveNotification 来合并两个上下文的变化。

由于 IOS 5 可以使用块代替为您进行合并。所以我决定使用这个而不是调度方式(这样我就不必使用通知)。

同样使用块时,当一个对象在后台队列中被选中而在另一个队列中被删除时,我遇到了同样的问题(错误)。所以我决定不立即删除它,而是为 OrderItem 插入一个 NSDate 'deleted' 属性。然后有一个带有删除检查的计时器,以查看是否有超过 10 分钟前被删除的对象。这样我确信没有缩略图仍在下载。有用。虽然我仍然想知道这是正确的方法:)

于 2013-03-03T18:55:17.967 回答