Свойство по сравнению с переменной экземпляра

Вы можете создать вычисляемый реквизит (например, parsedTabs) и удалить те вкладки, которые вы не хотите показывать, например:

parsedTabs() {
  return this.tabs.filter(tab => tab.size);
}
33
задан 5 April 2009 в 22:06
поделиться

6 ответов

Свойства являются просто методами set и методами считывания для ivars и должен (почти) всегда использоваться вместо прямого доступа.

@interface APerson : NSObject {
    // NSString *_name;           //  necessary for legacy runtime
}

@property(readwrite) NSString *name;

@end

@implementation APerson
@synthesize name;                 // use name = _name for legacy runtime
@end

@synthesize создает в этом случае те два метода (не точных 100%):

- (NSString *)name {
    return [[_name copy] autorelease];
}
- (void)setName:(NSString *)value {
    [value retain];
    [_name release];
    _name = value;
}

Легко теперь различать ivars и методы считывания/методы set. Средства доступа имеют self. префикс. Вы не должны получать доступ к переменным непосредственно так или иначе.


Ваш пример кода не работает, как это должно быть:

_myVar = some_other_object;      // _myVar is the ivar, not myVar.
self.myVar = some_other_object;  // works too, uses the accessors
28
ответ дан 27 November 2019 в 18:33
поделиться

В целом я называю свои свойства тем же как мои переменные экземпляра; это - предположение по умолчанию что @property синтаксис делает. Если Вы находите борьбу со значениями по умолчанию Вы делаете его неправильно (или Ваша платформа sux, который не имеет место для Cocoa/Cocoa-touch, по-моему).

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

self.stuff = @"foo"; // property setter
[stuff release]; // instance variable
stuff = @"bar"; // instance variable
return self.stuff; // property getter

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

-(void) someActionWithStuff: (NSString*) theStuff {
    // do something
    [stuff release];
    stuff = [theStuff copy];
    // do something else
}

чем это:

-(void) someActionWithStuff: (NSString*) theStuff {
    // do something
    self.stuff = theStuff;
    // do something else
}

Я предпочитаю делать управление памятью максимально явно. Но даже если Вы не соглашаетесь, с помощью self.stuff форма будет, подсказка в любом испытала программиста Objective-C, что Вы называете свойство вместо того, чтобы получить доступ к переменной экземпляра. Это - тонкий момент, который это легко для новичков замять, но после работы с Objective C 2.0 некоторое время это довольно ясно.

2
ответ дан 27 November 2019 в 18:33
поделиться

Называют синтезируемое свойство prop на самом деле представлен двумя методами prop (возвращение текущего значения свойства) и setProp: (устанавливание нового значения для опоры).

self.prop синтаксис является синтаксическим сахаром для вызова одного из этих средств доступа. В Вашем примере можно сделать любое из следующих для установки свойства myVar:

self.myVar = @"foo"; // handles retain/release as specified by your property declaration
[self setMyVar: @"foo"]; // handle retain/release
_myVar = @"Foo"; // does not release old object and does not retain the new object

К свойствам доступа использовать self.propname. К доступу переменные экземпляра используют просто имя переменной экземпляра.

8
ответ дан 27 November 2019 в 18:33
поделиться

Поскольку Apple резервирует префикс _ для себя, и поскольку я предпочитаю делать его более очевидным, когда я использую сеттер и когда я использую ivar, я принял Практика использования префикса i_ в моих ivars, например:

@interface MyClass : NSObject {
    NSString *i_myVar;
}

@property (nonatomic, retain) NSString *myVar;

@synthesize myVar = i_myVar;

i_myVar = [input retain];
self.myVar = anotherInput;
[i_myVar release]

Поскольку очень важно знать, когда вы используете установщик и когда вы используете ivar,

0
ответ дан 27 November 2019 в 18:33
поделиться

Проблема с использованием стратегии @synthesize myVar = _myVar заключается в том, что я полагал, что написание такого кода, как:

 myVar = some_other_object; // не работает.

Компилятор жалуется, что myVar не объявлен. Почему это так?

Потому что переменная myVar не объявлена.

Этот оператор использует синтаксис для доступа к переменной, будь то переменная экземпляра или какой-либо другой тип. Как сказал вам rincewind, для доступа к свойству вы должны использовать либо синтаксис доступа к свойству ( self.myVar = someOtherObject ), либо явное сообщение методу доступа ( [self setMyVar: someOtherObject] ).

В противном случае вы пытаетесь получить доступ к переменной, а поскольку у вас нет переменной с именем myVar , вы пытаетесь получить доступ к переменная, которой не существует.

5
ответ дан 27 November 2019 в 18:33
поделиться

Дон,

Согласно «правилам», вы должны вызывать Release для каждого копирования, распределения и сохранения. Так почему вы звоните в Release по разным вопросам? Предполагается ли, что он был создан с помощью Alloc, Copy или Retain?

Это поднимает другой вопрос: Вредно ли вызывать Release для ссылки на объект, если он уже был освобожден?

0
ответ дан 27 November 2019 в 18:33
поделиться