Распределение памяти, освобождение и NSURLConnection в приложении iPhone - PullRequest
0 голосов
/ 28 октября 2009

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

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

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

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

}

Класс загрузки данных

@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

Спасибо всем, Lee

1 Ответ

1 голос
/ 30 октября 2009

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

return [request urlData];
[request release];
...