2

initWithContentsOfURL を使用してフィードを解析しているときにタイムアウトを設定するにはどうすればよいですか? フィードが空白の応答を返す場合があり、フィードを永久に解析しようとします。30 秒程度のタイムアウトを設定して、UIAlertView をポップアップし、フィードの再解析を試みます。

    NSURL *feedURL = [[NSURL alloc] initWithString:URL];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:feedURL];
    [parser setDelegate:self];
    [parser setShouldProcessNamespaces:NO];
    [parser setShouldReportNamespacePrefixes:NO];
    [parser setShouldResolveExternalEntities:NO];

    [parser parse];
4

3 に答える 3

3

最初のアプローチ: 遅延セレクターの使用

おそらくこれを行う最も簡単な方法は、NSObject のperformSelector:withObject:afterDelay:メソッドを使用することです。次のようにいくつかのメソッドを定義できますparsingDidTimeout

- (void)parsingDidTimeout {
    if(self.parsingDidComplete == NO) {
        [self.parser abortParsing];
        // Create your error and display it here

        // Try the fetch and parse again...
    }
}

これには、パーサーをインスタンス変数 ( self.parser) として保持し、定義したメソッドからキャンセルできるようにする必要があります。また、パーサー デリゲートが、パーサーが終了したかどうかを追跡する必要があります (は、デリゲートのメソッドでデフォルトに設定および設定self.parsingDidCompleteできます)。これは、成功した解析が中止されるのを避けるためです。これが完了したら、必要なのは簡単ですNOYESparserDidEndDocument:

[self performSelector:@selector(parsingDidTimeout) withObject:nil afterDelay:30];

30 秒後、解析中止コードが呼び出され、必要なことは何でも実行できます。

2 番目のアプローチ: タイマーの使用

NSObject メソッド呼び出しの代わりにNSTimerを使用することで、timeout メソッドでこのアプローチ全体を (ほぼ間違いなく) 簡単にすることができます。そうすれば、パーサーが正常に終了した場合は、単純にタイマーを無効にifして、メソッド内の句を削除できますparsingDidTimeout(その結果、BOOLivar も削除されます)。タイマーの初期化は次のようになります。

NSTimer *timer = [NSTimer timerWithTimeInterval:30.0
                                         target:self
                                       selector:@selector(parsingDidTimeout)
                                       userInfo:nil
                                        repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
于 2009-12-04T20:55:51.690 に答える
1

質問の方向には答えませんがNSURLConnection、データをダウンロードしていた場合は、要求と応答のサイクル (および追加のスレッドなしの非同期性) を完全に制御できます。それinitWithContentsOfURL:が、カバーの下で行っていることです。

于 2009-12-04T20:56:35.643 に答える
0

NSTimerakaを使用した Swift 3 の例Timer

func startParseTimeoutTimer() {
    Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (_) in
        if (self.busy) {
            self.parser?.abortParsing()
            self.parser = nil
            print("Show UI as NOT busy; we aborted for timeout \(Thread.current.isMainThread)")
        }
    }

}
于 2017-03-20T15:33:31.960 に答える