Utiliser UIDocumentInteractionController pour afficher la presentPreviewAnimated: via UIWebView

j'aimerais intercepter les clics d'un des types de fichiers pris en charge de L'UIDocumentInteractionController et les afficher dans une vue modale (fournie par presentPreviewAnimated: Méthode du Controller Uidocumentinteraction). Cette vue modale fournit également le "Open in"... la fonctionnalité " ouvrir l'un de ces documents dans d'autres applications compatibles sur l'appareil. Le code ci-dessous interceptera ces clics, détectera si la chaîne D'URL a l'un des suffixes appropriés, chargera ceci data, écrivez-le dans le répertoire, relisez-le et enfin utilisez les données avec le presentPreviewAnimated: méthode. Je dois d'abord écrire les données dans le système de fichiers parce que le contrôleur UIDocumentInteractionController nécessite des données locales et ne peut pas utiliser les données directement à partir de L'URL (pour autant que j'ai lu).

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

j'ai aussi mettre en œuvre le délégué suivant les méthodes à utiliser la vue appropriée et de supprimer le fichier après le point de vue a été rejeté (previewDocumentFileName est une classe variable):

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

veuillez noter que la Documentation D'Apple mentionnait spécifiquement le fait que le contrôleur de documents devait être conservé manuellement, donc je l'ai fait. Je dois aussi être relâché, donc je le fais si le contrôleur n'a pas été utilisé (méthode top) et a essayé de le relâcher après qu'il ait été utilisé (méthode delegate), mais que le relâchement causait des accidents, donc je l'ai retiré et les choses semblent fonctionner bien de ce point de vue.

Avec l'arrière-plan de la façon, ma question a à voir avec le fait que tandis que ce code semble fonctionner dans le simulateur iPhone (le document en ligne est affiché correctement dans le presentPreviewAnimated: vue, bien que sans le ' Ouvrir...'dialogue qui ne peut pas être utilisé dans le sim), il ne montre pas le presentPreviewMethod: sur l'iPad sim ou sur mon iPhone ou mon iPad. Je crois que la méthode est appelée correctement, mais le presentPreviewAnimated: la méthode revient NO, ce qui signifie qu'il n'a pas pu afficher le document aperçu.

Pourquoi en serait-il? Est-ce que je ne sauvegarde pas correctement le fichier (et donc il n'est pas détecté en tant que *pdf ou *doc, etc)? Que pourrais-je faire d'autre de mal? Il y a très peu de documentation ou d'exemple de code en dehors de la Documentation Apple, donc j'espère qu'au moins ce code sera utile à quelqu'un, bien que je voudrais le faire fonctionner à 100% d'abord. Merci à l'avance.

30
demandé sur Ricky 2010-07-24 16:39:44

2 réponses

en Ignorant le fait que vous [docController retain] et [controller release] - je vous recommande d'essayer [docController autorelease]. Il y a une chance qu'il essaie de faire quelque chose immédiatement après votre retour, mais pas plus tard pendant l'exécution. Si c'est le cas, vous voulez libérer le contrôleur un peu plus tardautorelease. Si ça plante encore, vous ne possédez pas l'objet. Cependant, si vous êtes retaining, vous êtes responsable de l' releaseing. Une fois que vous avez autoreleased il, mettez-le à nil si vous n'essayez pas de toucher à nouveau.

1
répondu Daniel 2012-05-26 01:20:13

dans la méthode dealloc vous écrivez simplement

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

Pensez qu'il applaudir!

-1
répondu Saroj Kumar ojha 2012-09-17 15:29:26