0

RestKit .20 を使用して 2 つのオブジェクトをマップしています。2 番目のオブジェクトは最初のオブジェクトに依存します。したがって、最初の操作は 2 番目の操作の前に実行する必要があります。操作が完了すると、コントローラーはモデル オブジェクトを使用して適切な情報をテーブル ビューに表示します。

最初のオブジェクトには一意の ID があり、これを使用して URL 要求の一部を形成し、それに接続するオブジェクトを取得します。そのすべてが機能し、リクエストは情報を取得し、マッピングを正しく実行していますが、操作の順序はすべて間違っており、私はそれを理解することができません!

これが私がしたいことです:

  1. ビューが読み込まれ、最初のオブジェクトの読み込み/マッピングが開始されます。
  2. 最初のオブジェクトがロードされると、2 番目のオブジェクトがロード/マップされます。
  3. テーブル ビューがリロードされます。

何が起こるかは次のとおりです。

  1. ビューが読み込まれ、テーブル ビューが読み込まれます。
  2. 操作は最後に実行され、ブロック操作が実行されるたびにデータがリロードされます-私が望むソリューションではありませんが、それを機能させる唯一の方法です。

私が説明するのは難しいので、いくつかのコードをここに示します:(関係のないコードの割り当てを省略しました)

- (void)viewDidLoad
{
    [super viewDidLoad]; 
    [self loadFirstObjects];        
    //omitted code

}



- (void)loadFirstObjects {
    //omitted code

    [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
        self.pubRepos = mappingResult.array;
        [self loadSecondaryObjects];
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"ERROR: %@", error);
    }];

    [operation start];
}

- (void)loadSecondObjects
{
    for (FirstObject *firstObject in firstObjects) {

        //Omitted code

        [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
            SecondObject *secondObject = [mappingResult.array objectAtIndex:0];

            [secondObjects setObject:secondObject forKey:secondObject.idNum];
            [table reloadData];
        } failure:^(RKObjectRequestOperation *operation, NSError *error) {
            NSLog(@"ERROR: %@", error);
        }];

        [operation start];

    }
}

では、これを希望どおりに機能させるにはどうすればよいですか? 最初にリクエスト/マッピングを実行してから、すべての情報をテーブルにロードして更新できるようにしたいと考えています。テーブルのリロードとは別に、Web サービスから新しいデータを常にリロード/マップする必要があります。

つまり、ここでの最大の問題は、操作ブロックが実行されるタイミングを正確に制御するにはどうすればよいかということです。

4

1 に答える 1

1

これをかなり簡単に行う 1 つの方法は、 を使用することdispatch_groupです。メソッド-loadSecondObjectsは次のようになります。

- (void)loadSecondObjects
{
    dispatch_group_t group = dispatch_group_create();

    for (FirstObject *firstObject in firstObjects) {
        // Omitted code
        dispatch_group_enter(group);
        [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
            SecondObject *secondObject = [mappingResult.array objectAtIndex:0];
            [secondObjects setObject:secondObject forKey:secondObject.idNum];
            dispatch_group_leave(group);
        } failure:^(RKObjectRequestOperation *operation, NSError *error) {
            NSLog(@"ERROR: %@", error);
            dispatch_group_leave(group);
        }];

        [operation start];
    }

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        [table reloadData];
    });
}

本質的に、ここで起こっていることはdispatch_group、カウンターが次にゼロになったときに実行するブロックを設定できる追加機能を備えた便利なカウンターとして を使用しているということです。The counter starts at 0. 秒単位のオブジェクトの読み込みを開始するたびに ( を呼び出してdispatch_group_enter) カウンターをインクリメントし、完了 (または失敗) する秒単位のオブジェクトの読み込みごとに ( を呼び出してdispatch_group_leave) カウンターをデクリメントします。カウンターが 0 にdispatch_group_notifyなると、設定したブロックが実行されます (その時点で、すべての 2 番目のオブジェクトの読み込み操作が完了したことがわかります)。

PS: あなたのコードに保持/リリースっぽい呼び出しが見られなかったので、ARC を使用していると思います。そうでない場合はdispatch_release、グループに参加する必要があります。

于 2013-09-05T11:53:09.913 に答える