11

私は作成していNSMutableRequestます:

self.req = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];

タイムアウトは 10 秒に設定されています。これは、ユーザーがフィードバックを得るのにあまり長く待たされたくないためです。その後、次を作成しますNSURLSessionDataTask

NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response;
    if (error) {
        // this is where I get the timeout
    } 
    else if (httpResp.statusCode < 200 || httpResp.statusCode >= 300) {
        // handling error and giving feedback
    } 
    else {
        NSError *serializationError = nil;
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&serializationError];
    }
    [task resume];
}

問題は、サーバーがゲートウェイ タイムアウトになり、時間がかかることです。タイムアウト エラーが発生し、ユーザーにフィードバックしますが、タイムアウト エラーが原因で、次の API 呼び出しはすべて同じように失敗します。それを止める唯一の方法は、アプリを強制終了して最初からやり直すことです。タイムアウト エラーの後にタスクまたは接続を強制終了するために何かすべきことはありますか? タイムアウトを設定せず、サーバーからエラー コードを受信するまで待機すると、次のすべての呼び出しが完全に機能します (ただし、ユーザーはかなり待機します!)。

タスクをキャンセルしようとしました:

NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response;
    if (error) {
        // this is where I get the timeout
        [task cancel];
    } 
    ...
    [task resume];
}
4

4 に答える 4

5

あなたが開始したタスクを再開するのを見ませんでした。次のことを宣言する必要があります。

[task resume];

この行は、タスクが中断されている場合に再開します。

次のように NSURLSession を呼び出してみてください。

[NSURLSession sharedSessison] instead of self.session

次の方法でセッションを無効にします。

 [[NSURLSession sharedSession]invalidateAndCancel];

Apple のドキュメントから:

アプリがセッションを必要としなくなったら、invalidateAndCancel (未処理のタスクをキャンセルするため) または finishTasksAndInvalidate (オブジェクトを無効にする前に未処理のタスクを終了できるようにするため) を呼び出してセッションを無効にします。

    - (void)invalidateAndCancel

無効化されると、デリゲートおよびコールバック オブジェクトへの参照が壊れます。セッション オブジェクトは再利用できません。

完了まで未処理のタスクを実行できるようにするには、代わりに finishTasksAndInvalidate を呼び出します。

  - (void)finishTasksAndInvalidate

このメソッドは、タスクの終了を待たずにすぐに戻ります。セッションが無効になると、そのセッションで新しいタスクを作成できなくなりますが、既存のタスクは完了するまで続行されます。最後のタスクが終了し、セッションが最後のデリゲート呼び出しを行うと、デリゲート オブジェクトとコールバック オブジェクトへの参照が壊れます。セッション オブジェクトは再利用できません。

未処理のタスクをすべてキャンセルするには、代わりに invalidateAndCancel を呼び出します。

于 2015-07-15T13:05:59.560 に答える
1

ここでおそらく遭遇する問題は、タスクがキャンセルまたは完了していないため、セッションがそれ以上のタスクを受け入れることができないということです。Appleのドキュメントによると

タスクを作成したら、resume メソッドを呼び出してタスクを開始します。その後、セッションは、リクエストが終了または失敗するまで、タスクへの強い参照を維持します。

T_77 が提案したように、[NSURLSession sharedSession] を使用してみてください

また、この時点でもう 1 つやろうとしていることは、Instruments を使用して、セッション オブジェクトとタスクの間に作成された保持サイクルがあるかどうかを調べることです。

発生している可能性のあるもう 1 つのことは、要求が適切に形成されておらず、実行されていないか、ハングしているということです。URL を Web ビューにロードしようとしたときに、同様の問題に直面したことがあります。ページが読み込まれておらず、エラーもスローされていませんでした。URLリクエストも一度確認してみてください。

ありがとう、スラジュ

于 2015-07-24T10:42:42.503 に答える
0

次のコードのように、さまざまな方法でタイムアウトを設定できます

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.timeoutIntervalForRequest = timeout;
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:nil delegateQueue:nil];
于 2015-07-24T09:19:24.587 に答える
0

タイムアウトの原因として最も可能性が高いのは、DNS が存在しない IP アドレスに解決されたか、サーバーがクラッシュして再起動が必要になったことです。いずれにせよ、1 つの要求がタイムアウトで失敗した場合、より多くの要求もタイムアウトで失敗する可能性が高くなります。

サーバーが応答しない場合でも生き残ることができるように、アプリケーションを作成する必要があることは明らかです。

于 2015-07-17T15:01:15.737 に答える