2012-02-06 3 views
3

Я прочитал много тем о геттерах и сеттерах. Я знаю, что это такое и почему они полезны. Различные исходные претензии - это разные способы выпуска иваров. Здесь начинается мое замешательствоЭто правильный способ борьбы с иварами?

@interface CoolClass : NSObject 
{ 
    NSString *name; 
} 

@property (nonatomic, copy) NSString *name; 
@end 

@implementation CoolClass 
@synthesize name = _name; 

-(id)init 
{ 
    if(super = [self super]) 
    { 
    self.name = @"Jo"; 
    } 
    return self; 
} 

-(void)dealloc 
{ 
    [self.name release], self.name = nil; 
} 
@end 

Это правильный способ выпускать/освобождать иваров?

+1

возможно дубликат [Почему я не должен использовать сорбент, чтобы освободить недвижимость в Objective-C? ] (http://stackoverflow.com/questions/7262268/why-shouldnt-i-use-the-getter-to-release-a-property-in-objective-c) – jrturton

+0

@Profo Сообщение: я пропустил, что вы 'd написано 'super = [self super]' - это должно быть 'self = [super init]' – justin

+0

if ((super = [super init])) также должно быть написано с помощью double (()), чтобы избежать предупреждения компилятора. –

ответ

2

Вы хотите использовать аксессоры большую часть времени, но не в частично сконструированных состояниях, поскольку они могут иметь negative side-effects. Вот как это делается:

- (id)init 
{ 
    if((self = [super init])) { 
    // self.name = @"Jo"; << don't use accessors in initializer 

    _name = [@"Jo" copy]; << good 
    } 
    return self; 
} 
// added for another variation: 
- (id)initWithName:(NSString *)inName 
{ 
    if((self = [super init])) { 
    _name = [inName copy]; 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    // don't use accessors in dealloc 
    // don't release the result of a getter (release the result of the retained or copied result) 
    // [self.name release], self.name = nil; 

    // instead: 
    [_name release], _name = nil; 
    [super dealloc]; << compiler should have warned you about this one 
} 

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

+0

Почему вы не должны использовать аксессоры в инициализаторе? – CarlJ

+0

Что вы подразумеваете под "бессмертным"? – Profo

+1

@meccan вот пример, который я написал, который демонстрирует некоторые из вещей, которые могут пойти не так: http://stackoverflow.com/questions/5932677/initializing-a-property-dot-notation/5932733#5932733 – justin

1

Вот что я бы посоветовал:

@interface CoolClass : NSObject 
@property (nonatomic, copy) NSString *name; 
@end 

@implementation CoolClass 
@synthesize name = _name; 

-(id)init 
{ 
    if(super = [self super]) 
    { 
    self.name = @"Jo"; 
    } 
    return self; 
} 

-(void)dealloc 
{ 
    [_name release]; 
    [super dealloc]; 
} 

@end 

Примечания:

  1. Там нет необходимости явно объявлять Ивар внутри {...} в вашем заголовке. Они будут созданы автоматически при синтезе вашего имущества. Явные ивары - это устаревшая концепция, которая больше не нужна, начиная с примерно iOS 3.

  2. Вы не должны использовать self.name в dealloc, так как это вызывает метод getter, который может выполнять дополнительную работу за пределами простого извлечения ivar. Обычно рекомендуется использовать метод геттера, но в dealloc вы должны немедленно освободить ivar

  3. Рекомендуется установить иварцы в нуль после их освобождения, но опять же в dealloc это необязательно, потому что нет кода всегда выполняется после dealloc, поэтому указатель не будет ссылаться снова.

  4. Обычно (за пределами dealloc), если вы хотите выпустить ivar, вы должны установить его на ноль, используя сеттер следующим образом: self.name = nil; который автоматически отпустит его и установит в нуль. Это эквивалентно [_name release], _name = nil;

+0

@Justin известить выше, что self.name = @ "Jo" является интродуцированным, можете ли вы подтвердить это? – Profo

+0

@Nick Относительно # 3: болтающиеся ссылки в укусе 'dealloc'. это необычно, но это происходит. – justin

+0

Только в том случае, если dealloc подкласса нарушает правило «не делайте никакой работы». Например, если вы вызываете метод setter/getter, который ссылается на другие ivars. Если единственное, что вы положили в dealloc, - это заявления о выпуске и снятия с регистрации из уведомлений и наблюдателей KVO (как вы предполагали), все будет в порядке. –

1
@interface CoolClass : NSObject 
{ 
    NSString *name; 
} 

Здесь вы объявили переменную экземпляра 'имя'; В настоящее время нет необходимости объявлять ivars в файле заголовка. Просто используйте свойства и сделайте компилятор для синтеза ivar для вас.

@property (nonatomic, copy) NSString *name; 

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

В реализации вы хотите, чтобы синтезировать свою собственность:

@synthesize name = _name; 

Этот код указывает компилятору генерировать геттер и сеттер для недвижимости под названием «имя» и использовать переменную экземпляра с именем «_name» к значению магазина. Итак, теперь у вас есть два ivars - 'name' и '_name'.

Вот как метод инициализации хотел как:

-(id)init 
{ 
    if(self = [super init]) 
    { 
    name = @"This is ivar declared between {}"; 
    _name = @"synthesized ivar"; 

    } 
    return self; 
} 

И в dealloc:

-(void)dealloc 
{ 
    [name release]; 
    [_name release]; 
    [super dealloc]; 
} 
+0

Почему вы положили [название] дважды в свой dealloc? –

+0

@NickLockwood nagan, иллюстрирующий, что OP объявили два ивара. – justin

+0

Ах, хорошая точка - это научит меня читать skim-reading ;-) –

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