Iphone WebView导致了巨大的内存泄漏

Iphone WebView导致了巨大的内存泄漏,iphone,cocoa-touch,memory-management,uiwebview,Iphone,Cocoa Touch,Memory Management,Uiwebview,我的应用程序中有一个表视图控制器。每个单元格都是一个网站的名称。当点击一个单元格时,会创建一个web视图控制器,传递一个url并推送到该视图。 相当标准,对吧 如果我进出web视图的次数足够多,我就会收到内存警告,直到应用程序崩溃 在我的实现中,我看不到任何地方没有正确地发布任何内容。是否有一些webview特定的最佳实践或重要的委托方法我可能遗漏了 这让我抓狂,因为代码很少,但我似乎仍然找不到问题。 有没有人能帮我找出导致内存问题的原因,或者让我参考一篇文章或教程,这样我就可以看到如何正确地做

我的应用程序中有一个表视图控制器。每个单元格都是一个网站的名称。当点击一个单元格时,会创建一个web视图控制器,传递一个url并推送到该视图。 相当标准,对吧

如果我进出web视图的次数足够多,我就会收到内存警告,直到应用程序崩溃

在我的实现中,我看不到任何地方没有正确地发布任何内容。是否有一些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];
}
网络视图控制器

@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];
}

您仍然在
initWithPath
的末尾保留了对
self.view
的额外引用,该引用应被释放

再解释一下:
[[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];

避免UIWebView内存问题的一种方法是一次只创建一个webview,并在应用程序的整个生命周期中重用它。也就是说,不要释放它,而是重新使用它。

警告:不要调用if([self init]),但如果(self=[super init]),请考虑实现-(void)webView:(UIWebView*)webView没有失败加载witheror:(NSError*)错误,否则您的应用程序将被苹果拒绝。谢谢奥利弗。我不知道