2010-07-24 18 views
30

me gustaría para interceptar los clics de cualquiera de los supported file types de la UIDocumentInteractionController y los muestra en una vista modal (proporcionado por presentPreviewAnimated: método de UIDocumentInteractionController). Esta vista modal también proporciona la funcionalidad "Abrir en ..." para abrir cualquiera de estos documentos en otras aplicaciones compatibles en el dispositivo. El siguiente código interceptará estos clics, detectará si la cadena URL tiene alguno de los sufijos apropiados, cargará estos datos, los escribirá en el directorio, los leerá nuevamente y finalmente usará los datos con el método presentPreviewAnimated:. Primero tengo que escribir los datos en el sistema de archivos porque UIDocumentInteractionController requiere datos locales y no puede usar los datos directamente desde la URL (hasta donde he leído).Usando UIDocumentInteractionController para mostrar presentPreviewAnimated: via UIWebView

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { 
if (navigationType == UIWebViewNavigationTypeLinkClicked) { 
    ILog(@"URL loading for NavigationTypeLinkClicked: %@", request.URL.absoluteString); 

    if ([request.URL.absoluteString hasSuffix:@"pdf"] || [request.URL.absoluteString hasSuffix:@"doc"] || [request.URL.absoluteString hasSuffix:@"xls"] || [request.URL.absoluteString hasSuffix:@"ppt"] || [request.URL.absoluteString hasSuffix:@"rtf"] || [request.URL.absoluteString hasSuffix:@"key"] || [request.URL.absoluteString hasSuffix:@"numbers"] || [request.URL.absoluteString hasSuffix:@"pages"]) { 
    if (NSClassFromString(@"UIDocumentInteractionController")) { 
       NSArray *parts = [request.URL.absoluteString componentsSeparatedByString:@"/"]; 
       self.previewDocumentFileName = [parts lastObject]; 
       NSLog(@"The file name is %@", previewDocumentFileName); 

    // Get file online 
       NSData *fileOnline = [[NSData alloc] initWithContentsOfURL:request.URL]; 

    // Write file to the Documents directory 
       NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
       NSString *documentsDirectory = [paths objectAtIndex:0]; 
       if (!documentsDirectory) {NSLog(@"Documents directory not found!");} 
       NSString *appFile = [documentsDirectory stringByAppendingPathComponent:previewDocumentFileName]; 
       [fileOnline writeToFile:appFile atomically:YES]; 
    NSLog(@"Resource file '%@' has been written to the Documents directory from online", previewDocumentFileName); 
    [fileOnline release]; 

    // Get file again from Documents directory 
       NSURL *fileURL = [NSURL fileURLWithPath:appFile]; 

    UIDocumentInteractionController* docController = [UIDocumentInteractionController interactionControllerWithURL:fileURL]; 

    docController.delegate = self; 
    [docController retain]; 

    BOOL result = [docController presentPreviewAnimated:YES]; 

    if (!result) { 
    [docController release]; 
    } 
    return NO; 
    } 
    } 
} 

// Do lots of other URL-detecting stuff here 
} 

también puedo implementar los siguientes métodos de delegado para utilizar la vista apropiada y para eliminar el archivo después de que el punto de vista ha sido despedido (previewDocumentFileName es una variable de clase):

#pragma mark - 
#pragma mark Document Interaction Controller Delegate Methods 

- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller { 
return self; 
} 

- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller { 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:previewDocumentFileName]; 
NSFileManager *fileManager = [NSFileManager defaultManager]; 
[fileManager removeItemAtPath:appFile error:NULL]; 
//[controller release]; // Release here was causing crashes 
} 

Tenga en cuenta que la manzana La documentación mencionó específicamente el hecho de que el controlador del documento debía conservarse manualmente, así que lo hice. También necesito ser liberado, así que lo hago si el controlador no se usó (método superior) e intenté liberarlo después de que se usó (método de delegado), pero esa versión estaba causando bloqueos, así que lo eliminé y las cosas parecen estar trabajando bien desde ese punto de vista.

Con el fondo fuera del camino, mi pregunta tiene que ver con el hecho de que aunque este código parece funcionar en el simulador de iPhone (el documento en línea se muestra correctamente en la vista presentPreviewAnimated:, aunque sin el 'Abrir en. .. 'diálogo que no se puede usar en el simulador), no muestra el presentPreviewMethod: en el iPad sim o mis dispositivos iPhone o iPad reales. Creo que el método se está llamando correctamente, pero el método presentPreviewAnimated: está devolviendo NO, lo que significa que no fue capaz de mostrar la vista previa del documento.

¿Por qué sería esto? ¿No estoy guardando el archivo correctamente (y por lo tanto no se está detectando como * pdf o * doc, etc.)? ¿Qué más podría estar haciendo mal? Hay muy poca documentación o código de ejemplo, además de la documentación de Apple, así que espero que al menos este código sea útil para alguien, aunque me gustaría que funcione al 100% en primer lugar. Gracias por adelantado.

+0

'[docController release]': active el clang. debería encontrar que se genera una advertencia porque no posee el controlador. – jww

+0

'[liberación del controlador];' - esto causa bloqueos porque usted no es responsable de este objeto. Está provisto para ti en el parámetro. No lo ha asignado para poder liberarlo. –

+0

Está funcionando bien para mí. Gracias Ricky –

Respuesta

-1

en el método dealloc, se escribe

- (void)dealloc { 
[controller release]; 
controller = nil; 
[super dealloc]; 
} 

creo que va a trabajar alegría!

1

Ignorando el hecho de que [docController retain] y [controller release] - Te recomiendo que pruebes [docController autorelease]. Existe la posibilidad de que intente hacer algo inmediatamente después de que regrese, pero no más tarde durante la ejecución. Si ese es el caso, desea liberar el controlador un poco más tarde, que es para lo que autorelease es. Si aún falla, no eres dueño del objeto. Sin embargo, si es retain ing it, usted es responsable de release ing it. Una vez que lo hayas lanzado automáticamente, configúralo en nil para que no intentes volver a tocarlo.

Cuestiones relacionadas