1

ブロックを使用して RestKit を実験するテストを作成しました。RKRequest.onDidLoadResponseメインの UI スレッドで応答を取得するには、呼び出しを含める必要があると考えていましたdispatch_async()が、驚いたことに、これにより実行時例外が発生することが判明したため、それを取り出して、インターフェイスを非常にうまく更新することができました。

問題の私のコードは次のとおりです。

- (IBAction)loadSeasons:(UIButton *)sender {
    [[RKClient sharedClient] get:@"/api/v1/seasons" usingBlock:^(RKRequest* req) {
        req.onDidLoadResponse = ^(RKResponse* res) {
            NSLog(@"Request Performed: %@", res.bodyAsString);
            self.textResponse.text = res.bodyAsString;
            //dispatch_async(dispatch_get_main_queue(), ^{
            //    NSLog(@"In main queue: %@", res.bodyAsString);
            //});
        };
    }];
}

dispatch_asyncブロックのコメントを外すと、例外が発生します。では、いつこれを使用する必要があり、いつ使用する必要がないかをどのように知ることができますか? 実行中のコードがメインスレッド上にあるかどうかをテストする必要がありますか?

私はObjective-Cが初めてで、まだ始まったばかりなので、初心者の質問かもしれないことをお詫びします。

UPDATE : 上記のコードのコメントを外すと、次のことが起こります。

  1. (lldb)コンソールは青色のテキストを出力し、他の情報は提供されません。
  2. objc_msgSendの中断libobjc.A.dylib: is shown in the editor on0x1c2009b: movl 8(%edx), %edi with the message in green:Thread 1: EXC_BAD_ACCESS (code=1, address=0x40000008)`。
4

1 に答える 1

3

質問に答えるには、 を呼び出して現在のスレッドを確認できます[NSThread isMainThread]。ただし、問題に対してこれを行う必要はありません。実際、メイン スレッドで既に実行している場合は、実行ブロックをメイン スレッドにディスパッチすることは完全に合法です。

クラッシュは、ブロックの実行時に変数が保存される方法が原因です。最初のブロックが完了すると、変数によって使用されるスタック メモリが上書きされる可能性があるため、非同期NSLogステートメントが 2 番目のブロックで実行されるまでに、変数resは破棄されるため、ログ ステートメントで使用されたときにガベージを指し、トリガーします。クラッシュ。

__block完全を期すために、変数宣言を調べてください。res2番目のディスパッチブロックで参照可能にするには、最初のブロックでこれを宣言し、ディスパッチされたログステートメントで使用して、変数として宣言してヒープに移動する必要があると思います__block__block RKResponse* response = res;response

于 2012-11-16T05:29:52.340 に答える