20

バックグラウンド セッションを使用NSURLSessionDownloadTaskして、すべての REST 要求を達成しています。このようにして、アプリケーションがバックグラウンドまたはフォアグラウンドにあることを考える必要なく、同じコードを使用できます。

私のバックエンドはしばらく機能していませんでした。その機会を利用してNSURLSession、タイムアウトで がどのように動作するかをテストしました。

まったく驚いたことに、私のNSURLSessionTaskDelegateコールバックはまったく呼び出されません。NSURLRequestまたは でどのようなタイムアウトを設定しNSURLSessionConfigurationても、リクエストがタイムアウトで終了したことを通知する iOS からのコールバックを受け取ることはありません。

つまりNSURLSessionDownloadTask、バックグラウンド セッションを開始したときです。アプリケーションがバックグラウンドでもフォアグラウンドでも同じ動作が発生します。

サンプルコード:

- (void)launchDownloadTaskOnBackgroundSession {
    NSString *sessionIdentifier = @"com.mydomain.myapp.mySessionIdentifier";
    NSURLSessionConfiguration *backgroundSessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:sessionIdentifier];
    backgroundSessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;
    backgroundSessionConfiguration.timeoutIntervalForRequest = 40;
    backgroundSessionConfiguration.timeoutIntervalForResource = 65;
    NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration:backgroundSessionConfiguration delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.timeout.com/"]];
    request.timeoutInterval = 30;
    NSURLSessionDownloadTask *task = [backgroundSession downloadTaskWithRequest:request];
    [task resume];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    NSLog(@"URLSession:task:didCompleteWithError: id=%d, error=%@", task.taskIdentifier, error);
}

ただし、デフォルトのセッションを使用すると、30 秒 (リクエスト レベルで設定したタイムアウト) 後にエラー コールバックが返されます。

サンプルコード:

- (void)launchDownloadTaskOnDefaultSession {
    NSURLSessionConfiguration *defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    defaultSessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;
    defaultSessionConfiguration.timeoutIntervalForRequest = 40;
    defaultSessionConfiguration.timeoutIntervalForResource = 65;
    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultSessionConfiguration delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.timeout.com/"]];
    request.timeoutInterval = 30;
    NSURLSessionDownloadTask *task = [defaultSession downloadTaskWithRequest:request];
    [task resume];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    NSLog(@"URLSession:task:didCompleteWithError: id=%d, error=%@", task.taskIdentifier, error);
}

バックグラウンド セッションを使用する場合、タイムアウトの動作が異なることを示唆するドキュメントを見つけることができないようです。

誰もその問題にぶつかりましたか? それはバグですか、それとも機能ですか?

バグ レポートの作成を検討していますが、通常、バグ レポーター (6 か月) よりも SO (数分) の方がずっと早くフィードバックを得ることができます。

よろしく、

4

5 に答える 5

4

DownloadTask のタイムアウトは、NSURLSessionDownloadDelegate ではなく NSURLSessionTaskDelegate によってスローされます

downloadTask 中にタイムアウト (-1001) をトリガーするには:

ダウンロードが始まるまで待ちます。データ ダウンロードのパーセンテージ チャンクがトリガーされます。

URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:

次に、XCode デバッガーでアプリ全体を一時停止します。

30秒待ちます。

XCode デバッガー ボタンを使用してアプリの一時停止を解除する

サーバーからの http 接続がタイムアウトし、トリガーされます。

-1001 「リクエストがタイムアウトしました。」

#pragma mark -
#pragma mark NSURLSessionTaskDelegate - timeouts caught here not in DownloadTask delegates
#pragma mark -
- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{

    if(error){

        ErrorLog(@"ERROR: [%s] error:%@", __PRETTY_FUNCTION__,error);

        //-----------------------------------------------------------------------------------
        //-1001 "The request timed out." 
//        ERROR: [-[SNWebServicesManager URLSession:task:didCompleteWithError:]] error:Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x1247c42e0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://directory.clarksons.com/api/1/dataexport/ios/?lastUpdatedDate=01012014000000, NSErrorFailingURLKey=https://directory.clarksons.com/api/1/dataexport/ios/?lastUpdatedDate=01012014000000, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.}
        //-----------------------------------------------------------------------------------


    }else{
        NSLog(@"%s SESSION ENDED NO ERROR - other delegate methods should also be called so they will reset flags etc", __PRETTY_FUNCTION__);
    }
}
于 2016-01-18T16:04:55.820 に答える
0

私はまったく同じ問題に遭遇しました。私が見つけた 1 つの解決策は、2 つのセッションを使用することです。1 つはデフォルト構成を使用したフォアグラウンド ダウンロード用で、もう 1 つはバックグラウンド構成を使用したバックグラウンド ダウンロード用です。バックグラウンド/フォアグラウンドに変更すると、再開データが生成され、一方から他方に渡されます。しかし、別の解決策を見つけたかどうか疑問に思っています。

于 2015-08-27T09:07:15.577 に答える