WebView导致巨大的内存泄漏

时间:2011-05-06 13:49:43

标签: iphone cocoa-touch memory-management uiwebview

我的应用中有一个表视图控制器。每个单元格都是网站的名称。点击单元格时,会创建一个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];
}

2 个答案:

答案 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,并在应用程序的整个生命周期中重用它。也就是说,不要释放它,而是重复使用它。