iOS NSURLConnection内存泄漏

时间:2011-11-08 17:00:37

标签: iphone ios nsurlconnection ios5

我有这样的代码

#import "UIWebImageView.h"

@interface UIWebImageView (hiddenMethods)

- (void) initDefaults;

@end

@implementation UIWebImageView (hiddenMethods)

- (void) initDefaults
{
    self.showActivityIndicator = NO;
    self.activityIndicatorStyle = UIActivityIndicatorViewStyleWhite;
    self.activityIndicatorSize = CGSizeMake(20.0, 20.0);
    //data = [[NSMutableData alloc] init];
}

@end

@implementation UIWebImageView

@synthesize showActivityIndicator;
@synthesize activityIndicatorStyle;
@synthesize activityIndicatorSize;

- (id) init
{
    if (self = [super init])
    {
        [self initDefaults];
    }
    return self;
}

- (void) loadFromURL:(NSString *) url
{
    [self.image release];
    self.image = nil;
    request = [NSURLRequest requestWithURL:[NSURL URLWithString:url] 
                                             cachePolicy:NSURLRequestReturnCacheDataElseLoad
                                         timeoutInterval:30.0];

    if (connection == nil)
        connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    // activity indicator start
    indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:activityIndicatorStyle];
    indicator.frame = CGRectMake((self.frame.size.width - activityIndicatorSize.width)/2, (self.frame.size.height - activityIndicatorSize.height)/2,
                                 activityIndicatorSize.width, activityIndicatorSize.height);

    [self addSubview:indicator];
    [indicator startAnimating];
}

- (void) dealloc
{
    [data release];
    [indicator release];
    [connection release];
    [super dealloc];
}

#pragma mark -
#pragma mark connection delegate

- (void) connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)incrementalData 
{

    if (data == nil)
        data = [[NSMutableData alloc] initWithCapacity:2048];

    [data appendData:incrementalData];
}

- (void) connectionDidFinishLoading:(NSURLConnection *)theConnection 
{
    self.image = [UIImage imageWithData:data];

    [indicator removeFromSuperview];
    //data = nil;
    [data release], data = nil;
    [connection release], connection = nil;
    [indicator release], indicator = nil;
}

- (void) connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)error
{
    self.image = [UIImage imageNamed:@"icon.jpg"];
    [indicator removeFromSuperview];
    //data = nil;
    [data release], data = nil;
    [connection release], connection = nil;
    [indicator release], indicator = nil;
}

我正在使用它从网上下载图片。表格中每个单元格的一个图像。当图像没有离开屏幕时,它工作正常。但是当你快速滚动tableView并且某些图像在屏幕上没有完成加载时会出现大量内存泄漏。

我知道泄漏在哪里以及泄漏的原因。但我找不到解决方案。 有什么想法吗 ? 谢谢

对不起我的英文

更新

这是一个用于将图像添加到tableView

的代码
UIWebImageView *tmpImageView = [[UIWebImageView alloc] initWithFrame:CGRectMake(0, 0, 57, 76)];
    tmpImageView.showActivityIndicator = YES;
    tmpImageView.contentMode = UIViewContentModeScaleAspectFit;
    tmpImageView.activityIndicatorStyle = UIActivityIndicatorViewStyleGray;
    [tmpImageView loadFromURL:[[tableArray objectAtIndex:indexPath.row] objectForKey:@"picurl"]];
    [cell addSubview:tmpImageView];
    [tmpImageView release];

我正在重复=)它的泄漏只有在没有完成加载并且在滚动时离开屏幕

2 个答案:

答案 0 :(得分:1)

由于UIWebImageView对象的递归分配(考虑到您正在使用可重用的单元格),所以发生了泄漏。

您应该将代码更改为:

    UIWebImageView *tmpImageView = [cell viewWithTag:2011];

    if(!tmpImageView)
    {
    tmpImageView = [[UIWebImageView alloc] initWithFrame:CGRectMake(0, 0, 57, 76)];
        tmpImageView.showActivityIndicator = YES;
        tmpImageView.tag = 2011;
        tmpImageView.contentMode = UIViewContentModeScaleAspectFit;
        tmpImageView.activityIndicatorStyle = UIActivityIndicatorViewStyleGray;
        [cell addSubview:tmpImageView];
        [tmpImageView release];
    }


        [tmpImageView loadFromURL:[[tableArray objectAtIndex:indexPath.row] objectForKey:@"picurl"]];

你必须处理showActivityIndi​​cator的一些方法...基于你的代码,但上面提到的更改将消除你的内存泄漏。

答案 1 :(得分:1)

使用此语法自动解析NSURLConnection

connection = [NSURLConnection connectionWithRequest:request delegate:self];

并删除您的[connection release], connection = nil;