我的应用中有一个表视图控制器。每个单元格都是网站的名称。点击单元格时,会创建一个Web视图控制器,传递一个URL并推送到该视图。 很标准吧?
如果我进出网页视图足够多次,我会开始收到内存警告,直到应用崩溃。
我无法在我的实施中看到任何我没有正确发布任何内容的地方。我可能遗漏了一些特定于webview的最佳实践或重要的委托方法吗?
这让我抓狂,因为涉及的代码非常少,但我似乎仍然无法找到问题。 有人可以帮我发现是什么导致了这个内存问题,或者有人提到我的文章或教程,所以我可以看看如何正确地做到这一点?
表视图控制器
@implementation LinkListViewController
@synthesize linksArray;
@synthesize wvcontroller;
#pragma mark -
#pragma mark Initialization
- (void)loadView {
[super loadView];
table = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
[self pushViewController:table animated:YES];
table.tableView.delegate = self;
table.tableView.dataSource = self;
table.title = @"Links"; // Tab Bar Title
[self.view addSubview:table.view];
}
-(id) initWithTabBar {
if ([self init]) {
self.tabBarItem.image = [UIImage imageNamed:@"events.png"];
}
return self;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [linksArray count];;
}
#define LABEL_TAG 7777
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
LinkData *ld;
ld=[linksArray objectAtIndex:indexPath.row];
static NSString *CellIdentifier = @"Cell";
UILabel *label = nil;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
CGRect frame;
frame.origin.x = 0;
frame.origin.y = 10;
frame.size.width = 100;
frame.size.height = 30;
frame.origin.x = 0;
frame.size.width =290;
label = [[[UILabel alloc] initWithFrame:frame] autorelease];
label.tag = LABEL_TAG;
[cell.contentView addSubview:label];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
label = (UILabel *) [cell.contentView viewWithTag:LABEL_TAG];
}
label.text = [ld.linkname copy];
label.textColor=[UIColor blackColor];
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
LinkData *ld=[linksArray objectAtIndex:indexPath.row];
if ([ld.linktype isEqualToString:@"webpage"]) {
if (wvcontroller) {
[wvcontroller release];
wvcontroller=nil;
}
wvcontroller= [[WebViewController alloc]initWithPath:ld.linkurl];
wvcontroller.title=ld.linkname;
[table.navigationController pushViewController:wvcontroller animated:YES];
}
}
网络视图控制器
#import "WebViewController.h"
@implementation WebViewController
@synthesize webView;
@synthesize path;
@synthesize showsync;
@synthesize activity;
-(id)initWithPath:(NSString *)thepath
{
if ( [self init]) {
self.path= [thepath copy];
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[self.view setBackgroundColor:[UIColor blackColor]];
[self loadView];
}
return self;
}
- (void)loadView {
//Create a URL object.
webView = [[UIWebView alloc] initWithFrame:self.view.frame];
webView.autoresizesSubviews = YES;
webView.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
//set the web view delegates for the web view to be itself
self.webView.scalesPageToFit = YES;
self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
self.webView.delegate = self;
//Create a URL object.
NSURL *url = [NSURL URLWithString:path];
//URL Requst Object
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//add the web view to the content view
[self.view addSubview:webView];
//load the URL into the web view.
[webView loadRequest:requestObj];
//[webView release], webView = nil;
activity = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activity.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
activity.center = self.view.center;
[self.view addSubview: activity];
}
/*
If you need to do additional setup after loading the view, override viewDidLoad. */
- (void)viewDidLoad {
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.webView;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
[webView release];
[activity release];
webView=nil;
[path release];
[super dealloc];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
[activity startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[activity stopAnimating];
}
答案 0 :(得分:1)
您仍然需要self.view
initWithPath
的额外引用,该引用应该被释放。
更多解释:[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]]
为您提供保留计数为1的UIView
(因为您刚刚分配了它)。将其分配给self.view
会使其保留计数增加1,因此目前为2。取消分配控制器时,它会减少self.view
中对象的保留计数,但计数仍为1,因此永远不会取消分配。你应该这样做:
UIView* myView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view = myView;
[myView release];
答案 1 :(得分:0)
避免UIWebView内存问题的一种方法是一次只创建一个webview,并在应用程序的整个生命周期中重用它。也就是说,不要释放它,而是重复使用它。