iphone - свойства и переменные экземпляра - PullRequest
0 голосов
/ 18 января 2012

Предположим, у меня есть этот код ...

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?

спасибо.

Ответы [ 6 ]

3 голосов
/ 18 января 2012

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

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

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

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

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

0 голосов
/ 18 января 2012

Мои ответы:

  • НЕТ
  • YES
  • Попробуйте [_string release] вместо.
0 голосов
/ 18 января 2012

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

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

[_aString release]

вместо.

0 голосов
/ 18 января 2012

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

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

Ответы: -

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

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

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

0 голосов
/ 18 января 2012

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

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

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

...