我怎样才能检查一个NSData的Blob是有效的NSURLSessionDownloadTask的resumeData?

我有一个应用程序,使用新的NSURLSession API的后台下载。 当下载取消或以提供NSURLSessionDownloadTaskResumeData的方式失败时,我将存储数据blob,以便稍后可以恢复。 很less的时间我注意到在野外的崩溃:

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

这里发生错误,其中resumeDataNSData blob, sessionNSURLSession一个实例:

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

数据是由Apple API提供的,是序列化的,然后在以后的时间点进行反序列化。 它可能被损坏,但它永远不会为零(如if语句检查)。

如何提前检查resumeData是无效的,这样我就不会让应用程序崩溃?

这是苹果build议的解决方法:

 - (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'd了):我从一个苹果工程师的Twitter交stream中得到了这个,他build议做什么,我写了上面的实现

我还没有find如何判断数据是否有效的答案。

不过,我目前正在解决这个问题:

 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 } } 

其实,简历数据是一个plist文件。 它包含以下关键字:

  • NSURLSessionDownloadURL
  • NSURLSessionResumeBytesReceived
  • NSURLSessionResumeCurrentRequest
  • NSURLSessionResumeEntityTag
  • NSURLSessionResumeInfoTempFileName
  • NSURLSessionResumeInfoVersion
  • NSURLSessionResumeOriginalRequest
  • NSURLSessionResumeServerDownloadDate所以你需要做的步骤是:

    1. 检查数据是一个有效的plist;
    2. 检查plist是否有上面的键;
    3. 检查临时文件是否存在;