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 an UIView
, with an UIScrollView
(with private class _UIWebViewScrollView
) as subview. The loading of a PDF into the UIWebView
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 the UIWebView
knows this is a PDF file and a subview with a private class UIWebPDFView
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 into UIWebPDFView
and the PDF is displayed. The problem is when this insertion happens the UIWebPDFView
has its backgroundColor
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 the UIWebView
and set their backgroundColor
property to white, for example.
The good news is that the UIViewController
's method -viewDidLayoutSubviews
is called when the UIPDFPageView
is inserted into the UIWebView
's view hierarchy. So, in the end the solution is to have this objective-C code into our view controller:
-(void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// Assuming self.webView is our UIWebView
// We go though all sub views of the UIWebView and set their backgroundColor to white
UIView *v = self.webView;
while (v) {
v.backgroundColor = [UIColor whiteColor];
v = [v.subviews firstObject];
}
}
And in Swift:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
var v:UIView? = self.webView
while (v != nil) {
v!.backgroundColor = UIColor.whiteColor()
v = v!.subviews.first
}
}
Turn off WebKitDiskImageCacheEnabled and the black border goes away:
In applicationDidFinishLaunchingWithOptions add the following lines:
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitDiskImageCacheEnabled"];
[[NSUserDefaults standardUserDefaults] synchronize];
I assume it's a bit of a timing-thing because UIWebPDFView
is added as subview not until the rendering has finished and viewDidLayoutSubviews
is called before that happens. And because there is no event like didFinshedRendering i used a timer to check when UIWebPDFView
is added.
The following is working for me.
Put a instance variable in the in the header file or your class:
// instance variable for interval timer
NSTimer *BackgroundIntervalTimer;
Put these methods in the implementation file:
- (void)startUIWebViewBackgroundFixTimer {
// if > iOS 8 start fixing background color of UIWebPDFView
if (!SYSTEM_VERSION_LESS_THAN(@"8.0")) {
// hide pdfWebView until background fixed
self.pdfWebView.alpha = 0.0;
// start interval timer
BackgroundIntervalTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(fixBackground) userInfo:nil repeats:YES];
}
}
- (void)stopUIWebViewBackgroundFixTimer {
[BackgroundIntervalTimer invalidate];
BackgroundIntervalTimer = nil;
}
- (void)fixBackground {
// stop timer interval
[self stopUIWebViewBackgroundFixTimer];
// Assuming self.webView is our UIWebView
// We go though all sub views of the UIWebView and set their backgroundColor to white
UIView *v = self.pdfWebView;
while (v) {
//v.backgroundColor = [UIColor whiteColor];
v = [v.subviews firstObject];
if ([NSStringFromClass([v class]) isEqualToString:@"UIWebPDFView"]) {
[v setBackgroundColor:[UIColor whiteColor]];
// background set to white so fade view in and exit
[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.pdfWebView.alpha = 1.0;
}
completion:nil];
return;
}
}
// UIWebPDFView doesnt exist yet so exit and try later
[self startUIWebViewBackgroundFixTimer];
}
Now put this line right after the line where you load the pdf:
// if iOS 8 check if pdfWebView got subview of class UIWebPDFView
[self startUIWebViewBackgroundFixTimer];
Hints:
SYSTEM_VERSION_LESS_THAN
is a macro to enshure the code is only execuded on iOS 8 and above.self.pdfWebView
is your UIWebView.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With