我正在实现一个简单的应用内浏览器。在我的家庭视图(UITableViewController
)中,我有类似的内容:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
WebViewController *webViewController = [[WebViewController alloc] init];
switch (indexPath.row) {
case 0:
webViewController.stringURL = @"http://www.google.com";
break;
case 1:
webViewController.stringURL = @"http://www.bing.com";
break;
default:
webViewController.stringURL = @"http://stackoverflow.com";
break;
}
[self.navigationController pushViewController:webViewController animated:YES];
[webViewController release];
}
在我的主视图和webViewController
之间反复导航几次后,应用崩溃了。
在WebViewController
课程内,我只有[UIWebView *webView]
和[UIActivityIndicatorView *activityIndicator]
。两者都具有属性nonatomic, retain
。这是实施。
#import "WebViewController.h"
@implementation WebViewController
@synthesize webView, activityIndicator, stringURL;
- (void)dealloc
{
[self.webView release];
self.webView.delegate = nil;
[self.activityIndicator release];
[super dealloc];
}
-(void)loadView {
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view = contentView;
CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
webFrame.origin.y = 0.0f;
self.webView = [[UIWebView alloc] initWithFrame:webFrame];
self.webView.backgroundColor = [UIColor blueColor];
self.webView.scalesPageToFit = YES;
self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
self.webView.delegate = self;
[self.view addSubview: self.webView];
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.stringURL]]];
self.activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.activityIndicator.frame = CGRectMake(0.0, 0.0, 30.0, 30.0);
self.activityIndicator.center = self.view.center;
[self.view addSubview: self.activityIndicator];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadView];
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
// starting the load, show the activity indicator in the status bar
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[activityIndicator startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
// finished loading, hide the activity indicator in the status bar
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[activityIndicator stopAnimating];
}
@end
我刚刚使用 Zombies模板在Instruments中运行我的应用程序,其中显示-[UIWebView webView:didReceiveTitle:forFrame:]
是Zombie调用。但我仍然无法弄清楚究竟是什么问题。
(如果需要,请下载trace)
非常感谢任何帮助!
[更新]:
dealloc
函数中存在一个明显的错误。在我发布self.webView.delegate=nil;
之前,我应先致电self.webView
。对于那个很抱歉。不幸的是,在我修复它之后,应用程序仍以同样的方式崩溃。 [webViewController release];
,则崩溃实际上已经消失。但很明显,会有内存泄漏。答案 0 :(得分:3)
首先,移除loadView
中对viewDidLoad
的号召。当框架找不到XIB文件中提供的视图时,框架将调用该方法。其次,你的loadView
充满了内存泄漏。每次调用方法时,您都在分配,初始化和保留对象。因此,您将获得所有权两次并在dealloc中仅发布一次。
未正确释放对象。你应该做像alloc-init-autorelease这样的事情来解决这个问题。接下来的事情是,每次控制器加载时,由于您调用loadView
,您最终会创建两个Web视图对象和两个请求。当您重新分配时,您将失去对其中一个的引用。这里,标题中提到的问题就在于此。您无法重置将控制器作为委托的Web视图对象的委托。想象一下,您离开后不久就会完成一项请求。这里的消息将转到僵尸对象。这是一个很好的例子,说明为什么需要nil
代理人。
答案 1 :(得分:2)
- (void)dealloc
{
self.webView.delegate = nil;
[self.webView release];
[self.activityIndicator release];
[super dealloc];
}
试试这个dealloc
。您正在发布webview
,然后将delegate
设置为nil
。您应该首先将delegate
设置为nil
,然后将release
设置为{{1}}。希望这能解决问题。
答案 2 :(得分:1)
我认为正在发生的事情是你在页面仍在加载时返回,因此控制器被取消分配,然后webview完成加载。 尝试在viewDidUnload方法中调用[webView stopLoading]以确保不会发生这种情况。
答案 3 :(得分:0)
不知道这是否是你问题的原因,但这绝对是错误的:
[self.webView release];
self.webView.delegate = nil;
发布后,您无法(安全地)引用self.webView
!
答案 4 :(得分:0)
不是推送webViewController,而是将其视图添加到self.view。 不要叫[self loadView];在viewDidLoad。