¿Cómo puedo comprobar que un blob NSData es válido como resumeData para un NSURLSessionDownloadTask?

Tengo una aplicación que utiliza descargas en segundo plano con las nuevas API de NSURLSession . Cuando una descarga cancela o falla de tal manera que se proporciona NSURLSessionDownloadTaskResumeData , NSURLSessionDownloadTaskResumeData el blob de datos para que pueda reanudarse más tarde. Una pequeña cantidad del time noto un crash en la naturaleza:

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

El error ocurre aquí, donde resumeData es el blob NSData y la session es una instancia de NSURLSession :

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

Los datos son proporcionados por las API de Apple, se serializan y luego se deserializan en un momento posterior. Puede estar dañado, pero nunca es nulo (como verifica la instrucción if).

¿Cómo puedo verificar con anticipación que el resumeData no es válido para que no deje que la aplicación falle?

Esta es la solución sugerida por 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]; } 

Editar (iOS 7.1 ya no es NDA): Recibí esto de un intercambio de Twitter con un ingeniero de Apple, sugirió qué hacer y escribí la implementación anterior

No he encontrado una respuesta sobre cómo saber si los datos son válidos antes de time.

Sin embargo, actualmente estoy trabajando en torno al problema de la siguiente manera:

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

en realidad, los datos del curriculum vitae son un file de plist. contiene la siguiente key:

  • NSURLSessionDownloadURL
  • NSURLSessionResumeBytesReceived
  • NSURLSessionResumeCurrentRequest
  • NSURLSessionResumeEntityTag
  • NSURLSessionResumeInfoTempFileName
  • NSURLSessionResumeInfoVersion
  • NSURLSessionResumeOriginalRequest
  • NSURLSessionResumeServerDownloadDate, por lo que los pasos que debe seguir son:

    1. comprobar que los datos son válidos;
    2. verifique que las llaves tengan las llaves como se indica arriba;
    3. compruebe que el file temporal existe;