0

tableviewdata の最新のインターネット リクエストを (コア データ) エンティティに保存していますが、「障害」に関するエラー例外に問題があります。テーブルビューにロードされる最新の「ordersitems」を取得する「loadData」と、サムネイルをコアデータエンティティにキャッシュしようとする「loadThumbnails」の2つのメソッドがあります。この問題は、マネージド オブジェクトが削除され、サムネイル メソッドが引き続きそれにアクセスしようとすると発生します。loadThumbnails メソッドを停止するために変数 stopThumbnails を作成しましたが、問題は引き続き発生します。

画像を遅延ロードして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

これが正しいアプローチかどうかはわかりませんが、うまくいくので、これを答えとしてマークします。

バックグラウンドですべてを行うために、2 番目の nsmanagedobjectcontext (MOC) を使用し、変更をメイン MOC にマージしました。2 つのコンテキストの変更をマージするために NSManagedObjectContextDidSaveNotification を使用する必要がありましたが、ディスパッチ キューはうまく機能します。

IOS 5 以降では、代わりにブロックを使用してマージを行うことができます。そこで、ディスパッチ方法の代わりにこれを使用することにしました(この方法では、通知を使用する必要はありませんでした)。

また、ブロックを使用して、オブジェクトが別のキューで削除されている間にバックグラウンド キューで選択されたときに、同じ問題 (障害) が発生しました。そこで、すぐに削除する代わりに、OrderItem の NSDate 'deleted' プロパティを挿入することにしました。次に、10 分以上前に削除されたオブジェクトがあるかどうかを確認する削除チェック付きのタイマーを用意します。このようにして、サムネイルがまだダウンロードされていないと確信しています。できます。私はまだIDを知りたいと思っていますが、これは正しいアプローチです:)

于 2013-03-03T18:55:17.967 に答える