Проблема освобождения UIImageView после добавления в UIScrollView - PullRequest
0 голосов
/ 24 марта 2010

У меня проблема с памятью, связанная с UIImageView. После добавления этого представления в мой UIScrollView, если я пытаюсь освободить UIImageView, приложение вылетает. Согласно трассировке стека, что-то вызывает [UIImageView stopAnimating] после вызова [UIImageView dealloc]. Однако, если я не освобождаю представление, память никогда не освобождается, и я подтвердил, что после освобождения остается дополнительный вызов сохранения для представления ... что заставляет мои общие ассигнования быстро расти и, в конечном итоге, приводит к сбою приложения. после загрузки просмотра несколько раз. Я не уверен, что я делаю здесь неправильно, хотя ... Я не знаю, что пытается получить доступ к UIImageView после того, как он был выпущен. Ниже я включил соответствующий заголовок и код реализации (я использую платформу Three20, если это как-то связано с этим ... также, AppScrollView - это просто UIScrollView, который перенаправляет событие touchesEnded следующему респонденту):

Заголовок:

@interface PhotoHiResPreviewController : TTViewController <UIScrollViewDelegate> {

    NSString* imageURL;
    UIImage* hiResImage;
    UIImageView* imageView;
    UIView* mainView;
    AppScrollView* mainScrollView;
}

@property (nonatomic, retain) NSString* imageURL;
@property (nonatomic, retain) NSString* imageShortURL;
@property (nonatomic, retain) UIImage* hiResImage;
@property (nonatomic, retain) UIImageView* imageView;

- (id)initWithImageURL:(NSString*)imageTTURL;

Реализация:

@implementation PhotoHiResPreviewController

@synthesize imageURL, hiResImage, imageView;


- (id)initWithImageURL:(NSString*)imageTTURL {

    if (self = [super init]) {

        hiResImage = nil;

        NSString *documentsDirectory = [NSString stringWithString:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]];
        [self setImageURL:[NSString stringWithFormat:@"%@/%@.jpg", documentsDirectory, imageTTURL]];
    }
    return self;
}

- (void)loadView {

    [super loadView];

    // Initialize the scroll view   
    hiResImage = [UIImage imageWithContentsOfFile:self.imageURL];
    CGSize photoSize = [hiResImage size];
    mainScrollView = [[AppScrollView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    mainScrollView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
    mainScrollView.backgroundColor = [UIColor blackColor];
    mainScrollView.contentSize = photoSize;
    mainScrollView.contentMode = UIViewContentModeScaleAspectFit;
    mainScrollView.delegate = self;

    // Create the image view and add it to the scrollview.
    UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, photoSize.width, photoSize.height)];
    tempImageView.contentMode = UIViewContentModeCenter;
    [tempImageView setImage:hiResImage];
    self.imageView = tempImageView;
    [tempImageView release];    
    [mainScrollView addSubview:imageView];

    // Configure zooming.
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
    CGFloat widthRatio = screenSize.width / photoSize.width;
    CGFloat heightRatio = screenSize.height / photoSize.height;
    CGFloat initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;
    mainScrollView.maximumZoomScale = 3.0;
    mainScrollView.minimumZoomScale = initialZoom;
    mainScrollView.zoomScale = initialZoom;
    mainScrollView.bouncesZoom = YES;

    mainView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    mainView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
    mainView.backgroundColor = [UIColor blackColor];
    mainView.contentMode = UIViewContentModeScaleAspectFit;
    [mainView addSubview:mainScrollView];   

    // Add to view  
    self.view = mainView;
    [imageView release];
    [mainScrollView release];   
    [mainView release];
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return imageView;
}

- (void)dealloc {

    mainScrollView.delegate = nil;
    TT_RELEASE_SAFELY(imageURL);
    TT_RELEASE_SAFELY(hiResImage);
    [super dealloc];
}

Я не уверен, как обойти это. Если я удаляю вызов [imageView release] в конце метода loadView, все работает нормально ... но у меня есть массивные выделения, которые быстро поднимаются до предела. Однако, если я действительно освобождаю его, происходит вызов [UIImageView stopAnimating], который завершает работу приложения после освобождения представления.

Спасибо за любую помощь! Я бился головой об этом в течение нескольких дней. : -Р

Cheers, Иосия

Ответы [ 3 ]

1 голос
/ 24 марта 2010

Переместите выпуск imageView до точки, в которой вы его установили.Таким образом, вы освобождаете объект перед изменением, где указатель imageView указывает на:

// Create the image view and add it to the scrollview.
UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, photoSize.width, photoSize.height)];
tempImageView.contentMode = UIViewContentModeCenter;
[tempImageView setImage:hiResImage];
// release old object
[imageView release];
// set the pointer to point at a new object
self.imageView = tempImageView;
[tempImageView release];    
[mainScrollView addSubview:imageView];

Затем в нижней части вашего метода, где вы отпускаете другие объекты, удалите строку:

[imageView release];
0 голосов
/ 24 марта 2010

Почему вы создаете временный вид? Вы звоните loadView более одного раза?

self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, photoSize.width, photoSize.height)];
[self.imageView setContentMode:UIViewContentModeCenter];
[self.imageView setImage:hiResImage];
[mainScrollView addSubview:self.imageView];
[self.imageView release]

Или выпустить его в dealloc, так как это переменная экземпляра? addSubview сохраняет ваш UIImageView, поэтому было бы странно, если бы он потерпел крах, потому что объект отсутствует. Вы пытались установить точки останова?

0 голосов
/ 24 марта 2010

В идеале переменные уровня класса должны быть освобождены в методе dealloc () класса

Похоже, что imgView - переменная уровня класса, и вы освобождаете ее в конце вызова метода.

Если у вас есть переменная, которую вы хотите освободить в конце метода - это должна быть переменная уровня метода. Итак, в вашем случае попробуйте сделать imgView переменной уровня метода. Тогда вы сможете без проблем освободить его в конце метода

...