30 votes

Utilisation de UIDocumentInteractionController pour afficher presentPreviewAnimated: via UIWebView

Je tiens à intercepter les clics à partir de la pris en charge les types de fichiers de la UIDocumentInteractionController et de les afficher dans une vue modal (fourni par l' presentPreviewAnimated: méthode de UIDocumentInteractionController). Ce modal vue fournit également la fonction "Ouvrir Dans..." fonctionnalité permettant d'ouvrir l'un de ces documents dans d'autres applications compatibles sur l'appareil. Le code ci-dessous va intercepter ces clics, de détecter si l'URL de la chaîne a tout les suffixes, charger ces données, l'écrire dans le répertoire, le lire à nouveau et enfin utiliser les données avec l' presentPreviewAnimated: méthode. Je dois écrire les données dans le fichier du système d'abord parce que la UIDocumentInteractionController nécessite des données locales et ne peut pas utiliser les données directement à partir de l'URL (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 également de 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 variable de classe):

#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 ont mentionné le fait que le document contrôleur doit être maintenu manuellement, donc je l'ai fait. J'ai aussi besoin d'être relâché, alors je le fais si le contrôleur n'a pas été utilisé (en haut) et a tenté de le libérer après il a été utilisé (méthode du délégué), mais que la libération était provoquant des plantages, donc je l'ai enlevé et les choses semblent être fonctionne bien de ce point de vue.

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

Pourquoi en serait-il? Je ne suis pas d'enregistrer le fichier correctement (et donc il n'est pas détecté comme un *pdf ou *doc, etc)? Quoi d'autre pourrais-je fait de mal? Il y a très peu de documentation ou un exemple de code là en dehors de la Documentation d'Apple, donc j'espère que, à tout le moins, ce code sera utile à quelqu'un, même si j'aimerais le faire fonctionner à 100% de la première. Merci à l'avance.

1voto

Daniel Points 643

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

-1voto

Saroj Kumar ojha Points 195

dans la méthode dealloc vous écrivez simplement

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

Pensez que cela fonctionnera de joie!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X