Выделение памяти, освобождение и NSURLConnection в приложении для iPhone

Я надеюсь, что кто-нибудь сможет мне с этим помочь. Я изо всех сил пытаюсь найти ответ на простой вопрос. Между прочим, это мой первый крупный проект obj-c после многих лет использования c и c #, так что не стесняйтесь указывать на то, что у меня не получается.

У меня есть приложение для iPhone, предназначенное для загрузки альбома фотографий в UIScrollView. Он также имеет функцию случайного изображения, которая использует тот же процесс, но отображает только одно изображение. Работает это так:

  1. Прочтите внешний XML-канал (хранящийся на веб-сайте ruby-on-rails), который содержит путь к случайному URL-адресу фотографии после анализа.
  2. Содержимое URL-адреса загружается с помощью NSURLConnection to NSData.
  3. ScrollView создается и помещается
  4. Подкласс UIView выделяет UIImageView, выделяет UIImage с NSData, который инициирует UIImageView с UIimage и, наконец, добавляет изображение в UIView.
  5. Затем родительский вид добавляет UIView в UIScrollView, который затем выдвигается на передний план.

Этот процесс повторяется снова, когда требуется следующее случайное изображение. Он также использует тот же процесс при отображении всего альбома изображений, за исключением того, что несколько 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 показывает выделение при запуске, 2 показывает после загрузки первого изображения и 3 после того, как второе изображение.

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

Всем спасибо, Ли


person Lee M    schedule 28.10.2009    source источник
comment
Ответьте на этот аналогичный вопрос: stackoverflow .com / questions / 1632168 /.   -  person Epsilon Prime    schedule 29.10.2009


Ответы (1)


Выделяется пара вещей. Например, в классе URLDownload вызов [request release] никогда не будет достигнут, поскольку он помещен после оператора return.

return [request urlData];
[request release];
person Christopher Fairbairn    schedule 30.10.2009