I ran into this same problem; very annoying. I was able to resolve it by first making my WebViewController a UIScrollViewDelegate.
@interface WebViewController () <UIWebViewDelegate, UIScrollViewDelegate>
When I added some debug in the scrollViewDidScroll delegate to inspect some properties and see what was going on, I was able to observe the framework readjust my content offset to be CGPointZero (which causes it to go behind the navigation bar). By checking for that condition, you can basically nullify the effect by resetting it immediately.
So once the UIWebView finished loading, I calculate the actual inset that I need based on the height of the navigation bar and the status bar.
- (void)webViewDidFinishLoad:(UIWebView *)webView {
webView.scrollView.delegate = self;
float inset = self.navigationController.navigationBar.bounds.size.height +
[UIApplication sharedApplication].statusBarFrame.size.height;
webView.scrollView.contentInset = UIEdgeInsetsMake(inset, 0.0, 0.0, 0.0);
}
Then whenever I detect a scroll, I just prevent the offset from canceling out my contentInset. I excluded this effect from when the user was zoomed so the document didn't jump around if the user happened to land on this boundary.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if(scrollView.contentOffset.y == 0 && !scrollView.zooming)
[scrollView setContentOffset:CGPointMake(0.0, -(scrollView.contentInset.top))];
}
The advantage here is that you don't need to depend on any timing elements, and you don't see the PDF jump around when the dispatch executes. The actual contentInset you need is also dynamically determined.