Утечки памяти iOS, приводящие к сбою при смене контроллеров представления - PullRequest
0 голосов
/ 17 марта 2012

Я создал два контроллера представления, в которых есть UIImage анимации. Он часто падает и показывает утечки памяти в инструменте xcode.

Код моего контроллера-

- (void)viewDidLoad {
     NSArray *firstArray;
     firstArray = [NSArray arrayWithObjects:    
                    [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"up0001" ofType:@"png"]],
                    [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"up0002" ofType:@"png"]],
                                      ::
                                      ::
                   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"up0035" ofType:@"png"]], nil];


     imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];

     imgView = UIViewContentModeScaleToFill;

     [imgView setAnimationImages:firstArray];

     imgView.animationDuration = 1.75;

     imgView.animationRepeatCount = 0;

     [imgView startAnimating];

     [self.view addSubview: imgView];
}
- (void)dealloc {
    [super dealloc];
    [imgView release]; 
    imgView = nil;
}

И я изменяю viewcontrollers как мой rootviewcontroller, получая объект appdelegate и вызывая следующую функцию appdelegate в моем Appdelegate.m (Пожалуйста, предложите любой хороший подход)

- (void)changeRootViewController:(NSString *)controllerName
{

    if(self.viewController){
        [self.viewController.view removeFromSuperview];
        self.viewController=nil;
    }

    if (controllerName == @"ViewController") {
        ViewController *lviewController =[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
        self.viewController =  (RootViewController *)lviewController;
        [lviewController release];
        lviewController.view = nil;
        [self.window setRootViewController:self.viewController]; //LEAKS 100%
    } else if (controllerName == @"MainViewController") {
        // Use a different VC as roowViewController
        MainViewController *lviewController =[[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
        self.viewController =  (RootViewController *)lviewController;
        [lviewController release];
        lviewController.view = nil;
        [self.window setRootViewController:self.viewController]; //LEAKS 100%
    } else if (controllerName == @"SecondViewController") {
        // Use a different VC as roowViewController
        SecondViewController *lviewController =[[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
        self.viewController =  (RootViewController *)lviewController;
        [lviewController release];
        lviewController.view = nil;
        [self.window setRootViewController:self.viewController];  //LEAKS 100%
    }

    [self.window makeKeyAndVisible];
}

И вызывая это в моей соответствующей кнопке контроллера, нажмите как -

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate changeRootViewController:@"ViewController"];

OR

 AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate changeRootViewController:@"MainViewController"];

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

Ответы [ 3 ]

2 голосов
/ 17 марта 2012

Посмотрите на этот кусок кода:


if (controllerName == @"ViewController") {
        ViewController *lviewController =[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
        self.viewController =  (RootViewController *)lviewController;
        [lviewController release];
        lviewController.view = nil;
        [self.window setRootViewController:self.viewController]; //LEAKS 100%
    }

Когда вы выделяете «lviewController», его счетчик хранения равен 1; когда вы делаете «self.viewController», как я полагаю, viewController является сохраняемым свойством, тогда количество сохраненных значений lviewController увеличивается до 2; затем вы отпускаете его, балансируя предыдущее выделение, и сохраняете счетчик возвращается к 1; наконец, вы назначаете его для rootViewController, который является сохраняемым свойством, поэтому снова lviewController retain count равен 2; наконец, когда вы «меняете» контроллер представления в своем окне, lviewController освобождается, поэтому он сохраняет значение, равное 1. Как вы можете видеть, он никогда не будет освобожден. Это означает, что каждый раз, когда вы вызываете эту функцию, вы делаете утечку.

1 голос
/ 17 марта 2012

Вы должны изменить некоторые из ваших утверждений в вашем коде ..

Эта строка не имеет смысла ..

   imgView = UIViewContentModeScaleToFill;

Существует функция, с помощью которой вы должны установитьЗначение свойства UIImageView для UIViewContentModeScaleToFill найдите в документации UIImageView.

[imageView setContentMode:UIViewContentModeScaleToFill];

То же самое с этим ...

lviewController.view = nil; //Remove this from your code ..

И, наконец, измените имплментациюдля функции dealloc и помните, [super dealloc]; должен быть последним в любой реализации dealloc.

- (void)dealloc {
    [imgView release]; 
    imgView = nil;
    [super dealloc];
}
0 голосов
/ 17 марта 2012

Вероятная утечка связана с кодом внутри классов "SecondViewController", "MainViewController", "ViewController".Причина сбоя в том, что вы открываете изображение после того, как [super dealloc]

попробуйте это,

- (void)dealloc {

     [imgView release]; 
     imgView = nil;
     [super dealloc];
 }
...