2009-10-28 71 views
0

我希望有人能幫助我與此有關。我正在努力尋找一個應該是一個簡單問題的答案。順便說一句,這是我多年使用c和c#之後的第一個主要obj-c項目,所以請隨時指出我失敗的事情。內存分配,釋放和NSURLConnection的在iPhone應用程序

我設計的的照片專輯加載到一個UIScrollView一個iPhone應用程序。它也有一個隨機圖像功能,它使用相同的過程,但只顯示單個圖像。它的工作原理是這樣的:

  1. 閱讀一個外部XML提要(存儲在ruby-on-rails網站上),該提要包含經過解析的照片隨機URL的路徑。
  2. URL的內容使用NSURLConnection下載到NSData。
  3. 滾動型被創建並被推
  4. 子類的UIView allocs一個的UIImageView,allocs與NSData的一個UIImage其中,inits與UIImage的所述的UIImageView和最後添加的ImageView到了UIView。
  5. 父視圖然後添加了UIView到的UIScrollView,然後將其推到前面。需要下一個隨機圖像時當

此過程再次發生。它在顯示整個圖像相冊時也使用相同的過程,除了幾個UIViews被添加到UIScrollView。

問題是,儘管在適當的情況下使用release和delloc,但活動工具指示NSURLConnection和UIImage使用的內存在下一圖像請求時未從內存中釋放。通過將應用程序構建到iPhone上可以進一步證明這一點。連續請求多個圖像會導致應用程序崩潰,這可能是由內存消耗造成的。

下面是一些代碼因爲我無法將整個項目完成後,由於合同協議。

URLDownload類(使用數據下載)

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

} 

數據下載類

@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

謝謝大家, 李

+0

退房這種類似的問題後: http://stackoverflow.com/questions/1632168/當通話釋放 - 上NSURLConnection的委託方 – 2009-10-28 21:27:49

回答

1

一對夫婦的東西貼出來。例如,URLDownload類中調用[要求發佈]永遠不會達到其放在return語句

return [request urlData]; 
[request release];