我目前正在iOS 5.1中构建一个使用ARC的导航控制器应用程序。我经常需要显示网页,我创建了一个Web查看器,它只是一个UIWebView,旁边有一些自定义内容。当用户完成查看页面时,他们点击后退按钮,后退按钮应释放与自定义Web查看器关联的所有内存。我的问题是,当按下后退按钮时,所有内存似乎都没有被释放。我已经构建了一个玩具应用程序(on github),它只是几个按钮,每个按钮都有一个调用不同页面的第一响应者。
@implementation ViewController
-(IBAction)googlePressed:(id)sender
{
CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://www.google.com"];
[self.navigationController pushViewController:customWebView animated:NO];
}
-(IBAction)ksbwPressed:(id)sender
{
CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://www.ksbw.com/news/money/Yahoo-laying-off-2-000-workers-in-latest-purge/-/1850/10207484/-/oeyufvz/-/index.html"];
[self.navigationController pushViewController:customWebView animated:NO];
}
-(IBAction)feedProxyPressed:(id)sender
{
CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://feedproxy.google.com/~r/spaceheadlines/~3/kbL0jv9rbsg/15159-dallas-tornadoes-satellite-image.html"];
[self.navigationController pushViewController:customWebView animated:NO];
}
-(IBAction)cnnPressed:(id)sender
{
CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://www.cnn.com/2012/04/04/us/california-shooting/index.html?eref=rss_mostpopular"];
[self.navigationController pushViewController:customWebView animated:NO];
}
CustomWebView只是一个在UI中链接到UIWebView属性的UIWebView
@implementation CustomWebView
@synthesize webView, link;
- (id)initWithStringURL:(NSString *) stringURL
{
if (self = [super init]) {
link = stringURL;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:link];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[webView loadRequest:urlRequest];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
我的问题是,一旦加载了所有内容,我就将堆基线设置为初始ViewController。然后我在加载页面后检查堆,然后返回到ViewController并获得以下快照:
这表明在每次点击一个按钮并返回ViewController之后,即使CustomWebView都应该被释放,堆也会继续增长。
编辑:
可以找到上述示例项目on github
答案 0 :(得分:8)
我有同样的问题,我发现this little piece of magic
/*
There are several theories and rumors about UIWebView memory leaks, and how
to properly handle cleaning a UIWebView instance up before deallocation. This
method implements several of those recommendations.
#1: Various developers believe UIWebView may not properly throw away child
objects & views without forcing the UIWebView to load empty content before
dealloc.
Source: http://stackoverflow.com/questions/648396/does-uiwebview-leak-memory
*/
[webView loadHTMLString:@"" baseURL:nil];
/*
#2: Others claim that UIWebView's will leak if they are loading content
during dealloc.
Source: http://stackoverflow.com/questions/6124020/uiwebview-leaking
*/
[webView stopLoading];
/*
#3: Apple recommends setting the delegate to nil before deallocation:
"Important: Before releasing an instance of UIWebView for which you have set
a delegate, you must first set the UIWebView delegate property to nil before
disposing of the UIWebView instance. This can be done, for example, in the
dealloc method where you dispose of the UIWebView."
Source: UIWebViewDelegate class reference
*/
[webView setDelegate:nil];
/*
#4: If you're creating multiple child views for any given view, and you're
trying to deallocate an old child, that child is pointed to by the parent
view, and won't actually deallocate until that parent view dissapears. This
call below ensures that you are not creating many child views that will hang
around until the parent view is deallocated.
*/
[webView removeFromSuperview];
答案 1 :(得分:1)
我已经使用ARC一段时间了,我在过去发现,Web视图将保留所加载的内容,直到它被告知加载其他内容。我解决这个问题的方法是在视图中使用javascript调用将(或者已经)的dissapear方法如下:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.webView loadHTMLString:@"<html></html>" baseURL:nil];
}
这为我释放了记忆。
答案 2 :(得分:1)
UIWebView是一个内存猪,并没有很好地释放内存。我在你的CustomWebView类中调用了一个 - (void)dealloc调用,当按下Back按钮时,它会按预期调用。
您可以尝试[[NSURLCache sharedURLCache] removeAllCachedResponses]或使用然后释放您自己的NSURLCache副本,但坦率地说UIWebView 从不完全清理自己。
答案 3 :(得分:0)
我还没有使用过ARC,但是看看你的自定义webview代码,我认为你创建的网页浏览仍然存在。
如果您想确保您的网络视图被正确杀死,请确保在viewWill / DidDisappear中调用[webview stopLoading],并且无法访问webview。
(警告:如果你推动另一个视图,那么webview也会被杀死,所以一定要好好处理这些问题)
大多数情况下,我遇到了webViews的问题,即使在弹出viewController之后,回调某些webView委托方法也会使应用程序崩溃。 (我猜ARC阻止它崩溃)。
如果有帮助,请告诉我。
答案 4 :(得分:0)
布伦丹有几点:
您尚未发布足够的代码以确定发生了什么。但是为什么不让控制器拥有一个单一的UIWebView,而不是在每个按钮上创建另一个按钮,只需传递一个带有相关URL的字符串?这是一个更好的设计模式,可以保证您永远不会有多个。
答案 5 :(得分:0)
@interface WebViewViewController : UIViewController<UIWebViewDelegate>
- (void)viewDidLoad
{
[super viewDidLoad];
NSString* urlAddress = @"http://www.google.com";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
self.webView.delegate = self;
[self.webView loadRequest:requestObj];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[_webView stopLoading];
[_webView loadHTMLString:@"<html><head></head><body></body></html>" baseURL:nil];
[_webView stopLoading];
[_webView removeFromSuperview];
}
- (void)dealloc
{
[_webView stopLoading];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
[_webView stopLoading];
_webView = nil;
}