Ваша идиома, чтобы избежать предупреждений о "потенциальной утечке" с "отдаленными" релизами? - PullRequest
2 голосов
/ 23 февраля 2011

Имея дело с анимацией больших изображений, вы можете сделать это: просто выделите память для каждого из больших изображений ...

NSArray *imagesForLargeAnimation;

#define IMG(X) [[UIImage alloc] \
  initWithContentsOfFile:[[NSBundle mainBundle] \
    pathForResource:@X ofType:@"tif"]]

imagesForLargeAnimation  = [[NSArray alloc] initWithObjects:
                    IMG("01"),
// (since we are allocing that image, of course we must release it eventually.)
                    IMG("02"),
                    IMG("03"),
                    ....
                    IMG("42"),
                    nil];

animationArea.animationImages = imagesForLargeAnimation;
//blah blah...

Позже, когда анимация будет остановлена ​​и больше не будетпоказано на экране, чтобы очистить память, вам нужно сделать это:

-(void) cleanUpTheMemoryInTheBigAnimation
 {
 //blah blah..

 // for each of those big images in the array, release the memory:
 for (UIImage *uu in imagesForLargeAnimation)
    [uu release];

 // release the array itself
 [imagesForLargeAnimation release];
 imagesForLargeAnimation = nil;

Теперь все это работает отлично и эффективно, оно не будет пропускать или чрезмерно использовать память, если вы неоднократно будете использовать различные большие анимации.

Единственная проблема, конечно, в том, что вы получаете предупреждение лязга: «Потенциальная утечка объекта, расположенного в строке 69», действительно вы получаете оценки этих предупреждений, по одному на каждое выделение.

Чтолучший способ избежать этих предупреждений - и сделать его более безопасным и трудным?

Кто-нибудь знает?

Например, если вы используете autorelease, таким образом, в приведенном выше примере кода вы быиспользуйте autorelease в IMG define ...

... фактически, когда вы освобождаете NSArray (т. е. [imagesForLargeAnimation release]) ... в этот момент он автоматически освобождает все объекты вмассив?Это верно?Или ??

(или я должен использовать какую-то функцию newBlah для вставки изображений, или .. ??)

Если кто-нибудь знает правильный подход здесь, чтобы избежать "потенциального"утечка ", спасибо !!!

{PS напоминание о том, что в принципе никогда не следует использовать imageNamed:, это безнадежно: оно подходит только для небольших изображений типа использования пользовательского интерфейса.Никогда не используйте imageNamed!}

Ответы [ 3 ]

6 голосов
/ 23 февраля 2011

Вам не нужно сохранять изображения - NSArray сделает это за вас.

Попробуйте это:

#define IMG(X) [[[UIImage alloc] \
  initWithContentsOfFile:[[NSBundle mainBundle] \
    pathForResource:@X ofType:@"tif"]] autorelease]

, и теперь вам не нужен этот код:

// for each of those big images in the array, release the memory:
//for (UIImage *uu in imagesForLargeAnimation)
//    [uu release];

FYI (1):

Если бы вы использовали imageNamed, вы бы не получили предупреждение, потому что imageNamed возвращает уже автоматически выпущенные объекты, но alloc / initWithcontentsOfFile не делает:)


FYI (2):

В NSArrays существует метод, который выполняет селектор для всех объектов:

[imagesForLargeAnimation makeObjectsPerformSelector:@selector(release)];
1 голос
/ 23 февраля 2011

Как только вы добавите объект изображения в массив, вы должны освободить ссылку.Но так как вы используете макрос для их инициализации, у вас нет ссылки на объект, который вы добавляете в массив.Добавление autorelease к макросу обеспечит правильное освобождение ссылки.Другой способ сделать это - использовать цикл для инициализации объектов, добавить их в изменяемый массив, а затем освободить их.

Я предполагаю, что статический анализатор не может видеть, что вы освобождаете все объектыв массиве вручную.Но вы должны позаботиться об этом во время определения массива.

0 голосов
/ 23 февраля 2011

Вы также можете использовать метод класса imageNamed:.

imagesForLargeAnimation  = [[NSArray alloc] initWithObjects:[UIImage imageNamed:@"01"],
                                                            ..., 
                                                            [UIImage imageNamed:@"42"],
                                                            nil];
...