10

NSURLSession新しいAPIでバックグラウンド ダウンロードを使用するアプリがあります。提供されている方法でダウンロードがキャンセルまたは失敗した場合、NSURLSessionDownloadTaskResumeData後で再開できるようにデータ BLOB を保存します。ごくわずかな時間ですが、実際にクラッシュしていることに気付きます:

Fatal Exception: NSInvalidArgumentException
Invalid resume data for background download. Background downloads must use http or https and must download to an accessible file.

ここでエラーが発生します。ここで、resumeDataNSDataブロブで、sessionは のインスタンスですNSURLSession

if (resumeData) {
    downloadTask = [session downloadTaskWithResumeData:resumeData];
    ...

データは Apple API によって提供され、シリアル化され、後で逆シリアル化されます。壊れているかもしれませんが、(if ステートメントがチェックするように) nil になることはありません。

resumeDataアプリがクラッシュしないように、 が無効であることを事前に確認するにはどうすればよいですか?

4

3 に答える 3

25

これは、Apple が提案する回避策です。

- (BOOL)__isValidResumeData:(NSData *)data{
    if (!data || [data length] < 1) return NO;

    NSError *error;
    NSDictionary *resumeDictionary = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:NULL error:&error];
    if (!resumeDictionary || error) return NO;

    NSString *localFilePath = [resumeDictionary objectForKey:@"NSURLSessionResumeInfoLocalPath"];
    if ([localFilePath length] < 1) return NO;

    return [[NSFileManager defaultManager] fileExistsAtPath:localFilePath];
}

編集 (iOS 7.1 はもう NDA されていません): Apple エンジニアとの Twitter 交換からこれを入手しました。彼は何をすべきかを提案し、上記の実装を書きました

于 2014-03-03T02:09:09.783 に答える
2

データが有効かどうかを事前に確認する方法に対する答えは見つかりませんでした。

ただし、現在、次のように問題を回避しています。

NSData *resumeData = ...;
NSURLRequest *originalURLRequest = ...;
NSURLSessionDownloadTask *downloadTask = nil;

@try {
    downloadTask = [session downloadTaskWithResumeData:resumeData];
}
@catch (NSException *exception) {
    if ([NSInvalidArgumentException isEqualToString:exception.name]) {
        downloadTask = [session downloadTaskWithRequest:originalURLRequest];
    } else {
        @throw exception; // only swallow NSInvalidArgumentException for resumeData
    }
}
于 2014-02-24T17:58:46.643 に答える
1

実際には、履歴書データは plist ファイルです。次のキーが含まれています。

  • NSURLSessionDownloadURL
  • NSURLSessionResumeBytesReceived
  • NSURLSessionResumeCurrentRequest
  • NSURLSessionResumeEntityTag
  • NSURLSessionResumeInfoTempFileName
  • NSURLSessionResumeInfoVersion
  • NSURLSessionResumeOriginalRequest
  • NSURLSessionResumeServerDownloadDate したがって、実行する必要がある手順は次のとおりです。

    1. データが有効な plist であることを確認します。
    2. plist に上記のキーがあることを確認します。
    3. 一時ファイルが存在することを確認してください。
于 2015-11-20T01:29:00.813 に答える