Переменная Property vs. instance

Я пытаюсь понять, как страtagsи используют некоторые люди, чтобы отличать экземпляры vars от свойств. Общий шаблон выглядит следующим образом:

@interface MyClass : NSObject { NSString *_myVar; } @property (nonatomic, retain) NSString *myVar; @end @implementation MyClass @synthesize myVar = _myVar; 

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

 myVar = @"Foo"; 

Другой способ – ссылаться на него через себя. [Ivar / property here].

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

 myVar = some_other_object; // doesn't work. 

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

Благодарю.

Свойства – это просто сеттеры и геттеры для 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 и геттерами / сеттерами. У аксессуаров есть self. префикс. В любом случае вы не должны обращаться к переменным напрямую.


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

 _myVar = some_other_object; // _myVar is the ivar, not myVar. self.myVar = some_other_object; // works too, uses the accessors 

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

Синтаксис 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 . Для доступа к переменным экземпляра используйте только имя переменной экземпляра.

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

 myVar = some_other_object; // doesn't work. 

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

Поскольку переменная myVar не объявлена.

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

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

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

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

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

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

 -(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, это довольно ясно.

Дон,

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

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

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

 @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, я считаю, что явно другое имя безопаснее.

В вашем вопросе это должно быть:

 self.myVar = @"Foo"; // with setter, equivalent to [self setMyVar:@"Foo"] 

а также

 _myVar = some_other_object; // direct ivar access - no memory management! 

Помните, что вы не должны использовать сеттеры / геттеры в init / dealloc, поэтому вам нужно делать прямой доступ к IVAR (и аккуратное управление памятью) в этих методах.

что не так, просто используя

 @interface MyClass : NSObject @property NSString *prop; @end 

неатомические и удержание не требуются, сохранение по умолчанию, а атомное / неатомическое isn \ t важно, если XCode не сообщит вам предупреждение.

не нужно объявлять iVar, для вас будет создан _prop, если вы действительно хотите его использовать (я не понимаю, почему, если честно)

@synthesize НЕ требуется.

когда (и вы должны) использовать ARC, вам не нужно беспокоиться о сохранении и освобождении.

будь проще !

кроме того, если у вас есть такой метод, как этот

 - (void)aMethod:(NSString*)string { self.prop = string; // shows very clearly that we are setting the property of our object _aName = string; // what is _aName ? the _ is a convention, not a real visual help } 

я всегда использовал бы свойства, более гибкие, более легкие для чтения.

  • Измените NSEvent для отправки другого ключа, кроме того, который был нажат
  • создать подclass uibutton
  • Кто-нибудь реализовал API PayPal через собственное приложение для iPhone?
  • Проблема UITableView при использовании отдельного делегата / источника данных
  • Как я могу округлить значение float до двух постсимвольных позиций?
  • UIScrollView: подкачка по горизонтали, прокрутка по вертикали?
  • Сколько стоит разработка приложения для iPhone?
  • Должен ли я использовать NSUserDefaults или plist для хранения данных?
  • Apple Mach-O и множественные ошибки «неопределенных символов» с использованием OpenCV
  • Изменение позиции UIBarButtonItem в UINavigationBar
  • Msgstr "wait_fences: не удалось получить ответ: 10004003"?
  • Interesting Posts
    Давайте будем гением компьютера.