9

に電話するのは一般的に良い考え-[NSRunLoop runUntilDate:]ですか?問題なく動作しているように見えますが、実行ループ内から実行するように実行ループに指示するのは緊張します。

より詳しい情報:

現在、REST サービスからデータをフェッチするプロジェクトがあります。取得する必要がある重要な情報の 1 つは、有効なデータを含む日付の範囲です。これは非常に小さなデータで、一度だけ取得する必要があるため、これを処理する最善の方法は、ローカル変数がnil. 私は と を使用ASIHTTPRequestしているASINetworkQueueため、デフォルトではすべてが非同期であり、これが機能するためには、データがダウンロードされて処理されるまで、このプロパティを返すことはできません。これが私のコードの概要です。変数の名前は、罪のない人を保護するために変更されています。

__block BOOL isWorking = YES;
__block ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:/*actual URL*/] autorelease];
[request setCompletionBlock:^{
    // set local variable
    isWorking = NO;
}];
[request setFailedBlock:^{
    // show alert to user
    isWorking = NO;
}];
[queue addOperation:request];

while (isWorking) {
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}

繰り返しますが、これはうまく機能しているようです。このアプローチを使用する際に潜在的な問題はありますか?

4

2 に答える 2

4

ある種のスピナーを表示し、ネットワーク コードからの非同期完了イベントに応答して破棄する方がよいのではないでしょうか? お気に入り:

[self displayLoadingSpinner];
[request setCompletionBlock:^{
    [self handleSuccess];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self hideLoadingSpinner];
    }];
}];
[request setFailedBlock:^{
    [self handleFailure];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self hideLoadingSpinner];
    }];
}];
[queue addOperation:request];

これは、実行ループでモンキーするよりも優れていると思います。しかし、あなたはすでにこれを知っていて、ランループ ソリューションの正確な欠点を知りたいだけかもしれません。


値の準備ができるまでブロックしたい場合は、セマフォを使用できます。

dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[request setCompletionBlock:^{
    dispatch_semaphore_signal(sem);
}];
[queue addOperation:request];

dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_release(sem);
于 2011-02-07T17:59:32.410 に答える
3

オーバーラップする呼び出しツリーが完全に再入可能でない限り、呼び出している実行ループによって呼び出される可能性のあるメソッドからこれを行わないようにする必要があります。

Cocoa Touch UI コードは再入可能として文書化されていません (実際、そうではないという Apple DTS からの警告/ヒントがあります)。 -UI 実行ループで呼び出すことができる再入可能コード)、その内部から UI 実行ループを呼び出すことはお勧めしません。

于 2011-02-07T17:46:30.023 に答える