2011-09-27 2 views
0

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

- (id)initWithContentsOfFile:(NSString *)path 

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


Учитывая этот сценарий, предположим, что у меня есть класс, это может быть расширение любого класса. Например, взял 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

будет установлен в ноль, даже если распределение было сделано до инициализации.

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

+0

Я предлагаю придерживаться конвенции и начинать занятия с символов верхнего регистра. Вы облегчите свою жизнь (и если вы будете работать с другими людьми, вы не будете оскорблены и избиты ;-) – DarkDust

+0

дорогой DarkDust .. Я просто обсуждаю эту проблему. пожалуйста, не будьте настолько суровы ..! – samfisher

+0

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

ответ

1

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

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

От Handling Initialization Failure:

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

0

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

-(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; 
} 
+0

как вы можете вызвать initWithContentsOfFile после того, как вы уже сделали init в начале? – samfisher

+0

Хорошая точка. Я обновил код. – Davyd

1

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

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

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

    return self; 
} 

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

+0

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

+0

если я заменил -> return [self initWithContentsOfFile: путь]; with -> return [super initWithContentsOfFile: путь]; то это будет правильно? – samfisher

+2

@samfisher, если '[super init]' возвращает 'nil', супер' init' уже очистился после себя и освободил память, выделенную 'alloc'. В [другими словами] (http://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Chapters/ocAllocInit.html#//apple_ref/doc/uid/TP30001163-CH22-SW13), " вы должны вызвать метод release для себя только в момент сбоя. Если вы получите нуль от вызова инициализатора суперкласса, вам также не следует вызывать выпуск ». – albertamg

Смежные вопросы