Потенциальная проблема утечки при получении контроля над методом установки удерживаемого объекта - PullRequest
1 голос
/ 10 сентября 2011

Так вот мой код:

-(void)setMovie:(NSURL *)movieLocal {
    movie = movieLocal;
    [self.movie retain];
 ...
}

И я получаю эту ошибку:

Потенциальная утечка объекта, расположенного в строке 43

Строка 43 - [self.movie retain];. Я делаю что-то не так, и как я могу избавиться от этой ошибки?

Ответы [ 2 ]

2 голосов
/ 10 сентября 2011

Здесь есть пара проблем:

  • Старое значение movie никогда не сбрасывается
  • 'movie' и 'movieLocal' могут указывать на один и тот же объект. Если это так, вы будете вызывать удерживать на movie / movieLocal без последующего вызова сбалансированного выпуска.

Возможно, вы захотите использовать следующее:

-(void)setMovie:(NSURL *)movieLocal {
    if (movie == movieLocal) {
        return;
    }
    [movie release];
    movie = [movieLocal retain];
    //...
}
1 голос
/ 10 сентября 2011

Вот правильный установщик:

-(void)setMovie:(NSURL *)movieLocal {
    if (movie != movieLocal) {
        [movie release]; 
        movie = movieLocal;
        [movie retain];
    }
}

Однако, если вы объявили свою собственность (в файле .h):

@propert (nonatomic, retain) NSURL *movie;

и синтезируйте его в файле .m, @synthesize movie;, чем нет необходимости явно переопределять установщик - приведенный выше код будет сгенерирован автоматически для вас. Поэтому, когда вы захотите установить movie, вы просто позвоните self.movie = newMovie;, что будет эквивалентно вызову [self setMovie:newMovie];.

Для получения дополнительной информации прочитайте раздел «Объявленные свойства» в Learning Objective-C guide.

РЕДАКТИРОВАТЬ: объяснить, что случилось с вашим сеттером.

-(void)setMovie:(NSURL *)movieLocal {
    movie = movieLocal;     // first line
    [self.movie retain];    // second line
    ...
}

В 1-й строке вы присваиваете movie для указания на movieLocal, но вы не освобождаете старый NSURL объект, на который movie указывал перед назначением. Это было причиной того, что вы стали причиной утечки памяти - вы отказались от памяти, поэтому ваше приложение никогда не сможет вернуть ее обратно. В общем, отказ от памяти - это простой способ завершить работу приложения в iOS, когда объекты большие и часто протекают.

Во второй строке вы снова вызываете сеттер setMovie, так как синтаксис self.movie = заставляет среду выполнения вызывать сеттер для свойства movie. На этот раз это вызовет бесконечный цикл.

Надеюсь, моя формулировка была понятна для вас, а мой ответ полезен.

...