iPhone应用程序中的内存分配,发布和NSURLConnection

时间:2009-10-28 11:12:55

标签: iphone memory nsurlconnection alloc

我希望有人可以帮助我。我很难找到一个简单问题的答案。顺便说一句,这是我在使用c和c#多年后的第一个主要的obj-c项目,所以请随时指出我失败的事情。

我有一个iPhone应用程序,旨在将照片专辑加载到UIScrollView中。它还具有随机图像功能,该功能使用相同的过程但仅显示单个图像。它的工作原理如下:

  1. 读取外部XML Feed(存储在ruby-on-rails网站上),其中包含解析后随机网址的路径。
  2. 使用NSURLConnection将URL内容下载到NSData。
  3. 创建并推送ScrollView
  4. Subclassed UIView分配一个UIImageView,使用NSData分配一个UIImage,在UIImageView中使用UIimage,最后将imageview添加到UIView。
  5. 然后父视图将UIView添加到UIScrollView,然后将其推到前面。
  6. 当需要下一个随机图像时,再次发生此过程。除了将几个UIView添加到UIScrollView之外,它在显示整个图像专辑时也使用相同的过程。

    问题是,尽管在适当的地方使用了release和delloc,但活动工具指示在请求下一个图像时,NSURLConnection和UIImage使用的内存不会从内存中释放。通过在iPhone上构建应用程序进一步证明了这一点。连续请求多个图像会导致应用程序崩溃,可能是因为内存消耗。

    以下是一些代码,因为合同协议我无法发布整个项目。

    URLDownload类(使用DataDownload)

    @implementation URLDownload
        -(NSData *)GetURL:(NSURL *)strURL
    {
    
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        DataDownload *request = [DataDownload alloc];
    request.strURL = strURL;
    [request init];
    
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    while (request.isLoading && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
    
    [pool release];
    
    return [request urlData];
    [request release];
    
    }
    

    DataDownload类

    @implementation DataDownload
    @synthesize urlData, connection, strURL, isLoading;
    
    - (id)init
    {
    if(self = [super init])
    {
    
        self.isLoading = YES;
    
        NSURLRequest *dataRequest = [NSURLRequest requestWithURL:self.strURL
                                                 cachePolicy:NSURLRequestReloadIgnoringCacheData
                                             timeoutInterval:60];
    
        /* establish the connection */  
        self.connection = [[NSURLConnection alloc]
                     initWithRequest:dataRequest
                     delegate:self
        ];
    
        if (connection == nil) {
            self.urlData = nil; 
        } else {
            self.urlData = [NSMutableData data];   
        }
    
    }
    
    return self;
    
    }
    
    - (void)dealloc {
    [connection cancel];
    [connection release];
    [urlData release];
    [strURL release];
    [super dealloc];
    }
    
    - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
    return nil;
    }
    
     -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response
     {
    [urlData setLength:0];
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
     }
    
     -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)incrementalData
    {
    [self.urlData appendData:incrementalData];
    }
    
    -(void)connectionDidFinishLoading:(NSURLConnection*)connection
    {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    self.isLoading = NO;
    }
    
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
       self.isLoading = NO;
    }
    
    @end
    

    ImageView子类

    @implementation ImageView
    
    @synthesize strURL, imvImageView, image, currentlyRotated, imgOptionsView, startDate;
    
    - (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {       
    
        self.imvImageView = [UIImageView alloc];    
    
        if (self.strURL != nil){
            [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
            NSData *datImageData = [NSData dataWithContentsOfURL: [NSURL URLWithString:self.strURL]];
            [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    
            self.image = [UIImage imageWithData: datImageData];
    
    
            CGSize imgSize = image.size;
            CGFloat fltWidth = imgSize.width;
            CGFloat fltHeight = imgSize.height;
    
            [imvImageView initWithImage:image];
    
            // If landscape rotate image
            if (fltWidth > fltHeight){
                imvImageView.frame = CGRectMake(-80.0, 80.0, 480.0, 320.0);
    
                CGAffineTransform rotate = CGAffineTransformMakeRotation(-1.57079633);
                [imvImageView setTransform:rotate];
    
                self.currentlyRotated = YES;
            }else{
                imvImageView.frame = CGRectMake(0.0, 0.0, 320.0, 480.0);
    
                self.currentlyRotated = NO;
            }
    
            [image release];
        }else{
            self.image = [UIImage alloc];
            [imvImageView initWithImage:image];
            [image release];
        }
    
        [self addSubview:imvImageView];
    
    }
    
    [imvImageView release];
    
    return self;
    }
    
    - (void)drawRect:(CGRect)rect {
    // Drawing code
    }
    
    
    - (void)dealloc {
    [strURL release];
    [imvImageView release];
    [image release];
    [imgOptionsView release];
    [startDate release];
    [super dealloc];
    }
    

    图像显示方式的示例代码

    - (void)displayImage:(NSString *)strURL {
    NSString *strFullURL = @"http://www.marklatham.co.uk";
    strFullURL = [strFullURL stringByAppendingString:strURL];
    
    self.scroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0)];
    [scroller setContentSize:CGSizeMake(320.0, 540.0)];
    [self.view addSubview:scroller];
    
    CGRect rect = CGRectMake(0.0, 0.0, 320.0, 480.0);   
    self.imageView = [ImageView alloc];
    imageView.strURL = strFullURL;
    [imageView initWithFrame:rect];
    [scroller addSubview:imageView];
    
    [scroller release];
    [imageView release];
    
    }
    

    以下图片显示所有分配以说明正在发生的事情。图1显示启动时的alloc,在加载第一个图像后显示2个,在第二个图像后显示3个。

    http://www.gretanova.com/misc/iphone/1.png& 2.png& 3.png

    谢谢大家, 利

1 个答案:

答案 0 :(得分:1)

有几件事情发生了。例如,在URLDownload类中,永远不会达到对[request release]的调用,因为它放在return语句之后

return [request urlData];
[request release];