Создание автоматически освобожденного объекта в методе и возврат его в экземплярную переменную вызывает сбой - PullRequest
1 голос
/ 13 ноября 2010

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

Я написал метод для создания массива изображений и возврата этого массива. Это выглядит так:

- (NSMutableArray *)createImagesFor:(NSString *)animName withFrames:(int)numberFrames {
    NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:numberFrames];
    for (int i = 1; i <= numberFrames; ++i) {
        NSString *imageName = [[NSString alloc]initWithFormat:@"%@%i.png", animName, i];
        [imageArray addObject:[UIImage imageNamed:imageName]];
        [imageName release];
    }
    return imageArray;
}

Я называю это так:

NSMutableArray *imageArray;
imageArray = [self createImagesFor:@"jumping" withFrames:2];
self.animationImages = imageArray;
[imageArray release];

Однако, когда я запускаю анализатор сборки, он компилируется, но со следующей жалобой:

Потенциальная утечка объекта, расположенного на линии 109
1. Метод возвращает объект Objective-C со счетом удержания +1 (ссылка на владельца)
2. Объект, возвращенный вызывающей стороне в качестве исходной ссылки (единичное количество сохраненных данных, переданное вызывающей стороне)
3. Объект, размещенный в строке 109, возвращается из метода, имя которого ('createImagesFor: withFrames:') не содержит 'copy' или иным образом начинается с 'new' или 'alloc'. Это нарушает правила соглашения об именах, приведенные в Руководстве по управлению памятью для какао (объект просочился)

Я смотрел на документ управления памятью , но кроме автоматического высвобождения переменной (которая приводит к ее сбоям), я не уверен, в чем я ошибаюсь. Вот как я автоматически выпустил его:

NSMutableArray *imageArray = [[[NSMutableArray alloc] initWithCapacity:numberFrames]autorelease];

Я попытался сохранить * imageArray, как предложено здесь примерно так:

NSMutableArray *imageArray;
[imageArray retain];
    imageArray = [self createImagesFor:@"jumping" withFrames:2];
    self.animationImages = imageArray;
    [imageArray release];

Но это также дает сбой.

Анализатор предлагает мне изменить имя метода на что-то вроде 'newCreateImagesFor: withFrames:', но я не вижу, как это исправляет вещи?

Спасибо за помощь.

Майкл

Ответы [ 2 ]

5 голосов
/ 13 ноября 2010

Вам следует изменить последнюю строку первого блока кода на return [imageArray autorelease] и избавиться от выпуска во второй части (обычно вам не нужно освобождать объекты, возвращаемые вызовами методов).Вот о чем жалобы анализатора.Однако я не понимаю, почему это может вызвать сбой.

Как определяется свойство animationImages?Это может быть источником ваших проблем.

2 голосов
/ 13 ноября 2010
    - (NSMutableArray *)createImagesFor:(NSString *)animName withFrames:(int)numberFrames {
    NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:numberFrames];
    for (int i = 1; i <= numberFrames; ++i) {
        NSString *imageName = [[NSString alloc]initWithFormat:@"%@%i.png", animName, i];
        [imageArray addObject:[UIImage imageNamed:imageName]];
        [imageName release];
    }
    return imageArray;
}

возвращает объект imageArray, который имеет счет сохранения +1, но не был автоматически освобожден, статический анализатор clang предупредит вас об этом, и все это связано с соглашением об именовании, поскольку ваш метод не назван как как newImagesFor... или allocImagesFor... или copyImagesFor....


NSMutableArray *imageArray;

[imageArray retain];
// sending message to nil, does nothing

imageArray = [self createImagesFor:@"jumping" withFrames:2];
// imageArray has a retain count of 1
// and it is an autoreleased object

self.animationImages = imageArray; 

[imageArray release]; 
// retain count = 0, will be dealloc'd, 
// however it is already in the autorelease pool, 
// it will be over-released at the end of current event run loop

Когда вы объявляете imageArray, это нулевой указатель на класс NSMutableArray, отправка сообщения, в вашем случае retain, на нулевой указатель в Objective-C возможна и не вызовет исключения.


Если вы используете средство доступа к свойству для кэширования вашего объекта imageArray, ваше средство доступа к свойству должно быть объявлено, чтобы сохранить объект, назначенный вами

@property (retain) NSMutableArray *imageArray;

Теперь, когда ваш метод вернул автоматически освобожденный imageArray, и у вас есть правильный метод доступа к свойствам, все, что нужно, это

NSMutableArray *imageArray;
imageArray = [self createImagesFor:@"jumping" withFrames:2];
self.animationImages = imageArray;
...