UIWebView leaking when displaying large PDFs on iPad
Here's some strange behavior I hope someone can confirm is a known bug, or suggest a workaround.
My iPad app needs to display some large PDFs (~7mb and graphics-heavy.) The path of least resistance is of course a UIWebView, but my app crashes after display of a few. I isolated the behavior in a new project, and ran Instruments on it.
Here are the results. They seem to indicate that bad leaks are happening in UIWebView.
The essential code, in a minimal view controller:
-(IBAction)doPresent:(UIView *)sender
{
NSURL *url = [[NSBundle mainBundle] URLForResource:[NSString stringWithFormat:@"%d", [sender tag]]
withExtension:@"pdf"];
UIWebView *wv = [[[UIWebView alloc]开发者_运维知识库 init] autorelease];
UIViewController *vc = [[[UIViewController alloc] init] autorelease];
[vc setView:wv];
UINavigationController *holder = [[[UINavigationController alloc] initWithRootViewController:vc] autorelease];
[self presentModalViewController:holder animated:YES];
[wv loadRequest:[NSURLRequest requestWithURL:url]];
UIBarButtonItem *close = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:@selector(doDismiss:)] autorelease];
[[vc navigationItem] setRightBarButtonItem:close];
}
-(IBAction)doDismiss:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
Not pictured: the main nib containing this VC, its view, and five buttons connected to doPresent:
, each tagged with 1...5; and 1.pdf through 5.pdf in the app bundle. Run it and it works much as you'd expect, except that it crashes after a half-dozen or so views of the PDFs.
Running it under Instruments (allocations) yielded this interesting plot:
The pattern I notice is that, if I display a PDF and dismiss it without scrolling around the document, it's released as expected with minimal leakage. But if I touch it and scroll, even a little, the memory is not released. Viewing subsequent PDFs does not appear to reuse any of the wasted memory but each allocates more of its own. Running in the simulator and triggering memory warnings doesn't get this memory back either.
When usage hit ~ 25mb, the program got kill -9
'd. This seems low to me, suggesting some other resource is being leaked besides app memory.
This is on a iPad 1, running 4.3, freshly rebooted.
Ideas? Workarounds? Foolish omissions on my part?
Well, Apple finally got back to me on the bug report, and they recognize the bug and claim it's fixed in the latest ios 5.x builds. We'll see.
I think user:"drawnonward" is on to something. Looking at your code, with each button press you not only alloc and init a new webview, but also a new UIViewController, and a new UINavigationController. Unless it is absolutely necessary to create a new instance of each of these objects each time a button is pressed, you should re-code so that you have only one instance of each object, and then with each button press load new content into the webview.
I think there is a really good chance that this fixes your problem.
In my case I always go back from the PDF in the webview. If you scoll to top using something like this:
for (UIView *subview in webView.subviews)
{
if ([subview isKindOfClass:[UIScrollView class]])
[subview setContentOffset:CGPointZero animated:NO];
}
It seems to fix the issue
精彩评论