我怎样才能检查一个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.
这里发生错误,其中resumeData
是NSData
blob, session
是NSURLSession
一个实例:
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所以你需要做的步骤是:
- 检查数据是一个有效的plist;
- 检查plist是否有上面的键;
- 检查临时文件是否存在;