13

I am trying to preview pdf file in QLPreviewController and using the below code. It works fine on iOS7 and for other type of files (JPG/PNG) on iOS8 as well but when I try to open pdf it shows blank page instead content on iOS8. Its weird that it still shows name of pdf in title view.

Code:

QLPreviewController *previewer = [[QLPreviewController alloc] init];
previewer.dataSource = self;
previewer.currentPreviewItemIndex = 0;
[self presentViewController:previewer animated:NO completion:nil];

And QLPreviewControllerDataSource methods:

- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller {
    return 1;
}

- (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
    return [NSURL fileURLWithPath:self.pdfUrl];
}
sanjana
  • 2,974
  • 2
  • 23
  • 30

9 Answers9

5

This is actually a known issue in iOS 8 Beta 5.

See the URL under QuickLook https://developer.apple.com/library/prerelease/ios/releasenotes/General/RN-iOSSDK-8.0/

  • 2
    Removing QLPreviewController from UINavigationController solved my problem. In iOS SDK 8.0, QLPreviewController handles navigation bar & buttons on it. – Rahul Wakade Sep 25 '14 at 09:06
5

There seems to be a bug when placing a QLPreviewController inside of a UINavigationController. It just shows up as a black view even if the document is loaded.

UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:previewController];
[self presentViewController:navController animated:YES completion:nil];

The solution is to not use a navigation controller. QLPreviewController overrides the navigation bar anyways.

[self presentViewController:previewController animated:YES completion:nil];
CrimsonChris
  • 4,581
  • 2
  • 17
  • 30
  • 1
    This is not solving the issue. Still got the file name but not the file content. Anyone has a work-around ? – Chevenement David Sep 22 '14 at 17:19
  • 1
    Yup, this was my problem. Considered switching things over to a `UIDocumentInteractionController` but the `QLPreviewController` still works fine when taken out of a nav controller – Ian Hoar Sep 24 '14 at 20:11
5

There are probably two things here involved.

For those implementing QLPreviewController in a UINavigationController, there's probably an issue there.

For those still having the issue without the UINavigationController, read on.

In iOS 8.0, file path to Data has changed. So if you are using older bundle path to access your resources you might have an issue.

We did investigate this and it turns out:

  • that you need to pay close attention to the way you get the full path to the documents directory
  • that QLPreviewController CAN'T display a file in a subfolder of this Documents directory if you did not create it.

For instance, our problem was that our PDF file was opened from an outside application using the traditional "Open In".

This was resulting in the file being copied to the Inbox directory inside the Documents directory of the App.

The file IS displayed correctly on the simulator, regardless of the QLPreviewController being embedded in a UINavigationController or not.

The file IS NOT displayed correctly on a real iOS Device.

Before sending the file URL to the QLPReviewController, we did copy the file to the root of the Documents directory, passing this new URL to the QLPreviewController. And then bingo, it worked.

So in order to stop this issue, make sure you copy the resource in a directory you actually own. Until someone can explain how to play around with the rights on the Inbox (probably shared) directory.

nobody
  • 19,010
  • 17
  • 53
  • 73
  • Embedding the preview in a nav controller is definitely broken in iOS 8 . However, you are correct about them changing the document paths. – CrimsonChris Sep 23 '14 at 12:35
  • Did you try adding the QLPreviewController as the root view of a UINavigationController and then presenting it modally? – CrimsonChris Sep 25 '14 at 15:31
  • nope, we add it to view, which is added to a UInavigationController – Chevenement David Sep 26 '14 at 16:33
  • Then you may have found another workaround. Adding it as the root view controller of a UINavigationController will give you a black screen. – CrimsonChris Sep 26 '14 at 16:36
  • Yup, same here -- I can use either a nav controller or the `presentViewController` approach as long as I pre-copy the file out of the Inbox folder to the parent Documents folder; with Inbox I get only a display of the PDF file name and size. – jstevenco Dec 08 '14 at 19:49
  • I used afnetworking to download pdf file, then open it by QlPreviewController, then all times i got blank page... How to check my file url is being in document directory? Here is my url file: "file:///var/mobile/Containers/Data/Application/58B5C535-51FF-479E-82AA-039233CD0995/Documents/pdf-9.pdf" – kemdo Dec 18 '17 at 05:40
3

I just recently encountered a blank page again and I have found the reason to be that I did something like

previewController.dataSource = [[MyDataSource alloc] initWithSomething];

Since the QLPreviewController holds its dataSource as a weak variable, the data source immediately vanishes.

Keeping a strong reference to the dataSource helped.

DrMickeyLauer
  • 3,807
  • 3
  • 26
  • 59
  • Hello. I got this problem "[default] Unsupported preview item type in -previewItemViewControllerClassWithStyle:; for preview item - pdf-9 #PreviewItem" when preview pdf file. The URL is "file:///var/mobile/Containers/Data/Application/D7D1FE7B-9BE8-47B5-9F1F-6C1046B52B59/Documents/pdf-9.pdf" PLZ HELPPP – kemdo Dec 18 '17 at 03:12
2

Use this code if you in desperate need to use QLPreviewController embedded in UINavigationController:

#import <Quicklook/QLPreviewController.h>

...

QLPreviewController *pc = [[QLPreviewController alloc] init];
pc.delegate = self;
pc.dataSource = self;

UINavigationController *nc = [[UINavigationController alloc] init];
nc.view.backgroundColor = [UIColor whiteColor];
nc.navigationBarHidden = YES;

[self presentViewController:nc animated:YES completion:nil];
[nc pushViewController:pc animated:NO];
Alexander Abakumov
  • 10,817
  • 10
  • 71
  • 111
bteapot
  • 1,517
  • 11
  • 21
1

I had the same problem, and I needed to call reloadData() after I set the dataSource to a new value.

Jason
  • 385
  • 4
  • 10
0

Works fine with me on iOS8.1

Make sure you download the doc file into a proper file path

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachePath = [paths objectAtIndex:0];

urlString = [urlString stringByReplacingOccurrencesOfString:@"/" withString:@""];
 filePath = [cachePath stringByAppendingPathComponent:urlString];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if (fileExists == NO) {
    NSData *pdfData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:mainPadfLink]];
    [pdfData writeToFile:filePath atomically:YES];

}

and load it into your QLPreviewControl

- (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
    return [NSURL fileURLWithPath:filePath];
}

And make sure that you open the QLPreviewControl with presentViewController don't push it into your navigation controller

  • Works both ways for me in iOS 8.1. in iOS 7 I was returning 0 in the method - (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)previewController Dont know why it was working fine though :) It wasnt working in iOS 8. Returning 1 fixed the problem – Asbar Nov 11 '14 at 06:02
0

For iOS 9.2: In Monotouch.ios,

use

var url = NSUrl.FromFilename(NSBundle.MainBundle.PathForResource ("pdf.pdf", null)); 

instead of

var url = NSUrl.FromFilename("pdf.pdf");

It will work for all files. (jpg,png,pdf,etc)

satish
  • 21
  • 2
0

I had a problem (and still have) with presenting documents from bundle (xCode 9.2, iOS 11). It only displays images. For other documents (pdf, key, rtf, pages, docx, txt ...) it only shows the name and not the content. I'm presenting controller modally and the datasource is implemented like this:

func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
    return 1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {

    let url = Bundle.main.url(forResource: "test", withExtension: "pdf")!


    if QLPreviewController.canPreview(url as NSURL) {
        print("This file can be previewed.")
    } else {
        print("This file can not be previewed.")

    }
     return url as NSURL
}

Of course, it shows that file CAN be previewed, but it doesn't preview it. Currently I'm solving this by copying file to documents directory and passing that url to datasource.

Jovan Stankovic
  • 3,993
  • 3
  • 23
  • 15