Выпуск памяти - NSArray of UIImages - PullRequest
0 голосов
/ 14 марта 2011

У меня проблема с памятью. Я не могу понять, как работает текущий UIViewcontroller из navigationcontroller. Но я думаю, что это освободит память, по крайней мере, когда она заканчивается. Как вызвать метод dealloc. У меня есть класс, который наследует от UIViewController. Я в основном делаю последовательность анимации PNG. Я не могу использовать animationImages, потому что мне нужно немного перекрестного затухания. В любом случае, когда я наблюдаю за монитором активности и открываю страницу (наблюдаю, как объем памяти увеличивается на 30 МБ), я ее открываю. Объем памяти уменьшается на несколько МБ, но не на полный объем. Так что это продолжается до тех пор, пока приложение не вылетит. Детектор утечки не показывает никаких утечек. Я думаю, я позабочусь об этом. Я могу вставить свой код, если это поможет. Что-то я не понимаю в NavigationController и выпуске UIViewControllers?

Вот код:

-(void)addImage:(NSString*)imageName{
    if (!images){
        images = [[NSMutableArray alloc] init];
    }

//    UIImage*image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle]  pathForResource:[imageName stringByReplacingOccurrencesOfString:@".png" withString:@""] ofType:@"png"]];
    [images addObject:imageName];
  //  [image release];
}

-(UIImage*)getImage:(NSString*)imageName{
    return [UIImage imageNamed:imageName];
}

// left pad the image number with 0
-(NSString*)formatImageName:(int)num andName:(NSString*)imgName{
    NSString* imgNum = [NSString stringWithFormat:@"%i",num];
    if (num < 10){
        imgNum = [NSString stringWithFormat:@"0%i",num];
    }
    return [NSString stringWithFormat:imgName,imgNum];
}
// Returns a UIImageView that contains the next image to display
- (UIImageView *)nextImageView
{
    if(runOnce && hasRunOnce && pictureIndex == 0){
        return nil;
    }
    // get the image at the next index
    UIImage *image = [self getImage:[images objectAtIndex:pictureIndex]];
    ++pictureIndex; // increment the index




    // create an image view for the image
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    //[image release];

    // resize the image to fill the screen without distorting
    imageView.frame = rotator.frame;

    imageView.autoresizesSubviews = NO;
    [imageView setContentMode:UIViewContentModeCenter];


    // Makes the image move proportionally in any direction if the
    // bounds of the superview change when the iPhone is rotated.
    imageView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
                                  UIViewAutoresizingFlexibleRightMargin |                          
                                  UIViewAutoresizingFlexibleTopMargin |                            
                                  UIViewAutoresizingFlexibleBottomMargin);

    if(pictureIndex > images.count -1){
        pictureIndex = 0;
    }

    hasRunOnce = YES;
    return imageView;
}

- (void)timerFired:(NSTimer *)_timer{
    nextImageView = [self nextImageView];
    if(nextImageView){
        [self.view addSubview:nextImageView];
        nextImageView.alpha = 0.0;

        //NSLog(@"timerFired - image no: %i", pictureIndex);

        // begin animation block
        [UIView beginAnimations:nil context:nextImageView];
        [UIView setAnimationDuration:animationDuration]; // set the animation length
        [UIView setAnimationDelegate:self]; // set the animation delegate

        // call the given method when the animation ends
        [UIView setAnimationDidStopSelector:@selector(transitionFinished:finished:context:)];

        // make the next image appear with the chosen effect
        [nextImageView setAlpha:1.0]; // fade in the next image
        [currentImageView setAlpha:0.0]; // fade out the old image

        [UIView commitAnimations];
    } else {
        [timer invalidate];
        timer = nil;
    }

}

// called when the image transition animation finishes
- (void)transitionFinished:(NSString *)animationId finished:(BOOL)finished context:(void *)context
{
    [currentImageView removeFromSuperview]; // remove the old image
    currentImageView.image = nil;
    [currentImageView release]; // release the memory for the old image
    currentImageView = context; // assign the new image
}

-(void)startRotator{
    pictureIndex = 0; // reset the index

    currentImageView = [self nextImageView]; // load the first image
    [self.view addSubview:currentImageView]; // add the image to the view

    timer = [NSTimer scheduledTimerWithTimeInterval:scheduledInterval 
                                             target:self
                                           selector:@selector(timerFired:) 
                                           userInfo:nil 
                                            repeats:YES];
}

-(void)stopRotator{
    NSLog(@"ImageRotator - StopRotator Called");
    [timer invalidate];
    timer = nil; // set timer to nil
    [currentImageView removeFromSuperview]; // remove the current image
    currentImageView.image = nil;

    [currentImageView release];
    currentImageView = nil;
    if(nextImageView){
        [nextImageView removeFromSuperview]; // remove the current image
        nextImageView.image = nil;
        //[nextImageView release];
        nextImageView = nil;
    }
}

// called after this controller's view was dismissed, covered or otherwise hidden
- (void)viewWillDisappear:(BOOL)animated
{   
    [self stopRotator];
    [images release];
    images = nil;
    [super viewWillDisappear:animated];
}

Ответы [ 3 ]

1 голос
/ 14 марта 2011

Прежде всего, происходит резкое увеличение памяти, потому что вы храните все эти изображения в вашем массиве, для этого я бы предложил вам сохранить их в каталоге документов и адреса всех тех, кто находится в массиве (массив строк). Также одной из идей по уменьшению использования памяти будет использование

myImageView.image = nil;

если вы используете любой imageView для отображения изображения, используйте строку выше, когда вы не отображаете изображение. Следует помнить, что когда приложение выходит из памяти, оно вызывает

- (void)didReceiveMemoryWarning { 
}

не

- (void)dealloc {
}

Я бы предложил вам прочитать управление памятью

Также вы можете использовать Instruments для проверки на утечки памяти

0 голосов
/ 16 марта 2011

Проблема с памятью в итоге оказалась методом ImageNamed.Как только я использовал другой метод, переопределил его следующим образом, казалось, все работало нормально.

@implementation UIImage(imageNamed_Hack)
+ (UIImage *)imageNamed:(NSString *)name {
    return [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:name ofType:nil]];
}
@end
0 голосов
/ 14 марта 2011

Первое, что я думаю, вы должны изменить, это код ниже

- (void)timerFired:(NSTimer *)_timer
{
// all your code 
 .......
 .......
//add these two lines at bottom

[nextImageView release];
 //I think the leak is because you are adding imageViews and not releasing it .... when ever you add any subview to any view its retain count is incleased.
currentImageView.image = nil;
//also you are not using current view any more because you are setting its alfa to 0 so you can set its image to nil.

}

...