iOS - я запутался, как здесь обрабатывается память? - PullRequest
0 голосов
/ 27 сентября 2011

Справочный документ по API UIImage: -
initWithContentsOfFile:
Инициализирует и возвращает объект изображения с содержимым указанного файла.

- (id)initWithContentsOfFile:(NSString *)path

Параметры
путь
Путь к файлу. Этот путь должен включать расширение имени файла, определяющее тип данных изображения.
Возвращаемое значение Инициализированный UIImage объект , или nil , если метод не может найти файл или инициализировать изображение из его содержимого.


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

@interface myImage : UIImage
{
    BOOL isDefaultSet;
}

-(id)initWithDefaultImage;

@end

@implementation myImage


-(id)initWithDefaultImage
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"];

    idDefaultSet = YES;

    return [self initWithContentsOfFile:path];
}

@end


//somewhere in other class:

NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"];

myImage *myObject = [[myImage alloc] initWithDefaultImage];
UIImage *yourObject = [[UIImage alloc] initWithContentsOfFile:path];

теперь здесь в обоих случаях

«alloc» дает «retainCount + 1»

и если

initWithDefaultImage / initWithContentsOfFile

вернул ноль из-за какой-то проблемы - допустим (неверный путь к файлу), эта память будет вытекать как

MyObject / yourObject

будет установлен в ноль, даже если выделение было сделано до init .

Я видел много реализаций для расширенных классов / интерфейсов таким образом. Я запутался, как память обрабатывается здесь? Кто-нибудь может поделиться мнением по этому поводу?

Ответы [ 3 ]

1 голос
/ 27 сентября 2011

Обычно соответствующий инициализатор выпускает self (новый объект) перед возвратом nil, как в:

- (id)initWithFoo
{
    self = [super init];
    if (!self) return nil;

    if (someInitializingFailed) {
        [self release];
        return nil;
    }

    return self;
}

Можно предположить, что -[UIImage initWithContentsOfFile:] реализует тот же шаблон. Поэтому, если Instruments не сообщит вам о наличии утечки, вам не нужно выполнять никаких специальных действий в вашем случае.

1 голос
/ 27 сентября 2011

если [super init] возвращает nil, возвращается nil.поэтому элемент управления возвращается из метода, и блок if (someInitializingFailed) никогда не будет выполнен, а память будет просачиваться, так как alloc уже выполнен перед вызовом initWithFoo

, если [super init] возвращает nil, суперinit уже очистил после себя и освободил память, выделенную alloc.

Из Ошибка обработки инициализации :

Вы должны вызвать метод releaseна себя только в точке отказа.Если вы получите nil от вызова инициализатора суперкласса, вам также не следует вызывать release.

0 голосов
/ 27 сентября 2011

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

-(id)initWithDefaultImage
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"];
    if (path != nil)
    {
        self = [super initWithContentsOfFile:path];
    }
    else // cannot proceed with init
    {
        [self release];
        self = nil;
    }
    return self;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...