2012-01-18 3 views
0

Предположим, что у меня есть этот код ...iphone - свойства и переменные экземпляра

foo.h

@interface Foo : NSObject { 
    NSString *aString; // 1 
} 

@property (nonatomic, retain) NSString *aString; 

foo.m

@synthesize aString = _aString; 


.... 

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

Мои вопросы:

  • Мне действительно нужно объявить aString в «1»? (см. код)
  • если я синтезирую aString = _aString, я уже создаю экземпляр переменной, не так ли?
  • Если я сохраняю свойство на foo.h (@property), почему Xcode жалуется, если я выпущу aString в dealloc?

спасибо.

ответ

3

Вы смешиваете свойство и опорную переменную. «aString» - это свойство, к которому вы обращаетесь через вызов метода (например, [self aString]). «_aString» - это базовая переменная, к которой вы напрямую обращаетесь (например, _aString).

Принимая ваши вопросы по порядку:

  • No. Это неиспользуемая переменная, потому что вы сказали компилятору использовать _aString в качестве переменной. (На самом деле вам не нужно объявлять ни один из них в современном времени исполнения.)

  • Да, как указано в ответе на первый вопрос.

  • Поскольку компилятор ожидает, что вы отправите сообщение объекту, а «aString» не определено как указано. Обычно вы должны использовать [self aString] для доступа к объекту, но это особый случай: в -dealloc и in -initXYZ вы не используете методы доступа из-за потенциальных побочных эффектов. Переключитесь на [_aString release], и ​​все будет работать (если у вас нет ARC, в этом случае вы вообще не отпустите

+0

ах, я вижу, строка - это своего рода псевдоним для реального материала ...: D ... спасибо. Ваш ответ был прекрасен !!!!!! – SpaceDog

+0

Компилятор делает несколько вещей для вас за кулисами. Я написал подробный ответ (http://www.cocoabuilder.com/archive/cocoa/312413-code-error-in-your-first-mac-app-tutorial.html#312424) для кого-то на какао-dev mailing list a back back, если вы хотите лучше понять свойства. –

0

С вашей @synthesize переменная экземпляра (ваш «1») должна быть NSString* _aString.

Причина, по которой вы используете синтез с именованной переменной, заключается в том, что вы всегда используете self.aString для правильного выпуска старого объекта вместо случайной перезаписи указателя, напрямую изменяя aString.

У вас есть ARC включен? Если это так, вот почему Xcode жалуется на его выпуск.

+0

нет У меня нет дуги. Это проект, ориентированный на iOS 4.2 Что касается объявления _aString на «1», я согласен с тем, что это логично, но почему многие авторы этого не делают? Я видел много проектов, где парень просто объявляет его на @property и синтезирует. – SpaceDog

-1

Ответы: -

мне действительно нужно объявить aString в "1"? (см. код). Теперь с iOS 4 вам не нужно будет объявлять.

Если я синтезирую aString = _aString, я уже создаю переменную экземпляра, правильно? - Да

Если я сохраняю свойство на foo.h (@property), почему Xcode жалуется, если я выпущу aString в dealloc? - теперь вам нужно использовать это - self.aString = nil, это позаботится.

+1

Неверный ответ. НЕ используйте аксессоры в dealloc - например, self.aString = nil. Это может иметь непреднамеренные последствия. –

+0

Правильно. Никогда не используйте аксессоры в dealloc или init. –

+0

Почему Downvote, в то же время упоминается в Objective-C 2.0 для Apple, p74 - Если вы используют современную среду исполнения и синтезируют переменную экземпляра, однако вы не можете получить доступ к экземпляру var напрямую, поэтому вы должны вызвать метод доступа. Вы можете проверить это и сказать мне, где я ошибаюсь. – rishi

0

Чтобы ответить на ваши вопросы в порядке:

  • Нет. Там могу какое-то «лучшая практика» потому, что я пропускаю, но @property будет синтезировать переменный экземпляр, а также.
  • Когда вы объявляете aString = _aString, то, что вы можете сделать, непосредственно манипулирует _aString без доступа к синтезированному приемнику/сеттеру (путем вызова _aString) или использовать синтезированные геттер/сеттеры (путем вызова self.aString).
  • Возможно, вы выпустили его где-то в другом месте, кто-то еще его выпустил, или вы используете ARC. С NSStrings (и другими простыми объектами, которые имеют метод глубокой копии, легко доступны), я считаю, что лучше всего использовать @property (copy) и _aString = [stringPassedToInit copy], так что вы единственный, кто обрабатывает счетчик вашей строки. Если вы используете ARC, вам не нужно беспокоиться о сохранении/выпуске в большинстве случаев.
0

Нет, вам больше не нужно объявлять ivars (так как iOS 3 я думаю). Вы можете удалить всю {...} часть декларации интерфейса, и это не будет иметь никакого значения.

Жалоба, потому что ваш ivar назван _aString, а не aString. Вы должны сказать

[_aString release] 

вместо этого.

+0

нет, я не использую ARC. Вы имеете в виду, что мне не нужно объявлять ivars для свойств, не так ли? другие ivars я должен объявить ... – SpaceDog

+0

Да, если вы синтезируете свойство, вам не нужно объявлять ivar для него. Вы можете использовать свойства для всего и не использовать ivars вообще, что является лучшей практикой. Если вы хотите, чтобы ваши свойства были приватными, объявите их внутри частного интерфейса в вашем файле .m, а не в вашем .h-файле. –

-1

Мои ответы:

  • NO
  • ДА
  • Попробуйте [_string release] вместо этого.
Смежные вопросы