在 IOS6 中使用 Core Data(删除/编辑)

Posted

技术标签:

【中文标题】在 IOS6 中使用 Core Data(删除/编辑)【英文标题】:Using Core Data in IOS6 (delete/edit) 【发布时间】:2013-03-01 15:18:24 【问题描述】:

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

什么是延迟加载图像并将它们保存到 coredata 但检查对象是否未被删除的正确 ios 6 方法?我发现这个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;
        );
    );


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

【问题讨论】:

【参考方案1】:

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

为了在后台执行所有操作,我使用了第二个 nsmanagedobjectcontext (MOC),然后将更改合并到主 MOC。尽管我必须使用 NSManagedObjectContextDidSaveNotification 来合并两个上下文的更改,但调度队列效果很好。

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

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

【讨论】:

以上是关于在 IOS6 中使用 Core Data(删除/编辑)的主要内容,如果未能解决你的问题,请参考以下文章

iCloud Core Data iOS 6 到 iOS 7 最初是空的本地后备存储

使用 iCloud 在多台设备上同步 Core Data

了解如何将 UISearchBar 与 Core Data 一起使用

RestKit / Core Data:远程删除的实体不会从 Core Data 中删除

使用 Restkit 在 Core Data 中删除后保存对象使其崩溃

如何在 Swift 中从 Core Data 中删除数据时删除 UITableView 行?