Использование UIDocumentInteractionController для отображения presentPreviewAnimated: через UIWebView - PullRequest
30 голосов
/ 24 июля 2010

Я хотел бы перехватить щелчки в любом из поддерживаемых типов файлов UIDocumentInteractionController и отобразить их в модальном представлении (предоставляется методом presentPreviewAnimated: UIDocumentInteractionController). Это модальное представление также предоставляет функцию «Открыть в ...» для открытия любого из этих документов в других совместимых приложениях на устройстве. Приведенный ниже код будет перехватывать эти клики, определять, имеет ли строка URL какой-либо из соответствующих суффиксов, загружать эти данные, записывать их в каталог, читать снова и, наконец, использовать данные с методом presentPreviewAnimated:. Сначала мне нужно записать данные в файловую систему, потому что UIDocumentInteractionController требует локальных данных и не может использовать данные непосредственно из URL (насколько я читал).

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

Я также реализую следующие методы-делегаты для использования соответствующего представления и удаления файла после того, как представление было отклонено (previewDocumentFileName является переменной класса):

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

Обратите внимание, что в документации Apple особо упоминается тот факт, что контроллер документов необходимо было сохранить вручную, поэтому я сделал это. Я также должен быть освобожден, поэтому я делаю это, если контроллер не использовался (метод top) и пытался освободить его после его использования (метод делегата), но этот выпуск вызывал сбои, поэтому я удалил его, и все кажется чтобы работать с этой точки зрения нормально.

С учетом фона, мой вопрос связан с тем фактом, что хотя этот код работает в симуляторе iPhone (онлайн-документ отображается правильно в представлении presentPreviewAnimated:, но без 'Open In' ... », который не может быть использован в симе), он не показывает presentPreviewMethod: на симке iPad или моих реальных устройствах iPhone или iPad. Я считаю, что метод вызывается правильно, но метод presentPreviewAnimated: возвращает NO, что означает, что он не смог отобразить предварительный просмотр документа.

С чего бы это? Я не сохраняю файл должным образом (и поэтому он не определяется как * pdf или * doc и т. Д.)? Что еще я могу делать не так? Существует очень мало документации или примеров кода, кроме документации Apple, поэтому я надеюсь, что по крайней мере этот код будет кому-то полезен, хотя я бы хотел, чтобы он работал на 100% в первую очередь. Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 26 мая 2012

Игнорируя тот факт, что вы [docController retain] и [controller release] - я рекомендую вам попробовать [docController autorelease].Есть вероятность, что он пытается что-то сделать сразу после вашего возвращения, но не позже во время выполнения.Если это так, вы хотите выпустить контроллер чуть позже , для чего autorelease.Если он все еще падает, вы не являетесь владельцем объекта.Хотя, если вы retain это делаете, вы несете ответственность за release это.После того, как вы автоматически освободили его, установите для него значение nil, чтобы не пытаться снова его коснуться.

0 голосов
/ 13 апреля 2012

в методе dealloc вы просто пишете

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

думаю, что это будет работать ура! * * 1004

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...