In iOS 8, when rendering a .PDF into a UIWebview
there is a black border and background around the PDF displayed (not the whole background view). Note this is not the UIWebview background which is set to:
myWebView.opaque = NO;
myWebView.backgroundColor = [UIColor clearColor];
This is not present in < iOS8, (no black bordering coloured background around the .PDF)
Anyone else experienced this who could shed some light on this?
Im loading my PDF into the Web view like so..
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.pdfData != nil && self.viewHasUnloaded == YES) {
self.viewHasUnloaded = NO;
[self.webView loadData:self.pdfData MIMEType:@"application/pdf" textEncodingName:@"utf-8" baseURL:nil];
}
}
After a bit of investigating the issue I managed to understand where the problem is. So the
UIWebView
is anUIView
, with anUIScrollView
(with private class_UIWebViewScrollView
) as subview. The loading of a PDF into theUIWebView
goes under the following flow:1)
UIWebView
starts loading the request. By this time-webViewDidStartLoad:
delegate method is called.2) After the PDF is (down)loaded the delegate method
-webViewDidFinishLoad:
is called. By that time theUIWebView
knows this is a PDF file and a subview with a private classUIWebPDFView
is already inserted into the_UIWebViewScrollView
, but the PDF itself is not rendered, yet.And here comes the problem.
3) The PDF is rendered offscreen and after it's ready a new subview with private class
UIPDFPageView
is inserted intoUIWebPDFView
and the PDF is displayed. The problem is when this insertion happens theUIWebPDFView
has itsbackgroundColor
set to black and this insertion happens after the-webViewDidFinishLoad:
is called (the time depends on how big the PDF is to render). That's why it's not a good solution to go through all subviews of theUIWebView
and set theirbackgroundColor
property to white, for example.The good news is that the
UIViewController
's method-viewDidLayoutSubviews
is called when theUIPDFPageView
is inserted into theUIWebView
's view hierarchy. So, in the end the solution is to have this objective-C code into our view controller:And in Swift:
I had this exact same issue, plus I was trying to zoom into my pdf after it had loaded. If this code was called prematurely it would render the pdf un-useable - you could not pan/scroll the pdf at all, you could still pinch to zoom but it only zoomed into the very top-left corner.
I initially had some code to remove the black border and zoom into the pdf after a given delay like so;
The 0.6s delay is useless though. It would (sometimes) still not be long enough when testing on an (in use) iPhone 4S. On the latest devices, a 0.6s hit in performance is ridiculous when it worked with a <0.05s delay.
@graver's solution helped me to investigate the issue. As suggested I was running
NSLog(@"%@", v);
in the while loop (I was also runningNSLog(@"-------------");
before the while loop).I was also calling
viewDidLayoutSubviews
after a delay of 0.6s like so;These are my logs:
As you can see,
UIPDFPageView
does not appear until right at the end - the third and final timeviewDidLayoutSubviews
was called from the delay.EDIT: This is a very similar principle to @Heiko's answer but uses a recursive method rather than a timer.
There must be a better solution, such as detecting a change in the
webViews
subviews, but this solution works for now:Please excuse the method and variable names, I will come up with more appropriate ones tomorrow!
As you can see, it is a recursive method which calls itself until the pdf has loaded. There is a cap to avoid any infinite loops (there should be an alert or something if it has not loaded in this time). The cap is 20 and the delay is 0.05s which allows 1 second for the pdf to load. I will probably increase the cap to 40, but I think 0.05 is ok performance wise, but I need to conduct some proper testing.
I hope this has been insightful, but I'd really appreciate some feedback or improvements to this solution.
I've made the answer in Swift. Feel free to use:
PDFView is the name of my UIWebView.
This is a mix of Heiko and gravers answers.
The view responsible for the black background is an instance of UIWebPDFView. So we can use gravers' approach, but without making every UIWebView subview white (which will mess the pages indicator).
Also, this solution makes no assumption on the
UIWebPDFView
position in the view hierarchy.We recursively descend on all subviews, changing only the UIWebPDFView's backgroundColor.
I have the same problem..Unable to fix it using the suggested solution i have also tried setting the back ground color in webViewDidFinishLoad delegate fucntion but of no use..
NSLog content :
The simplest, but not so ideal fix is to add a border around the UIWebView of the same color as your pdf document's background color. This will prevent the ugliness to some extent until Apple fixes the issue.