Подтвердить что ты не робот

Когда я должен использовать @synthesize явно?

Насколько я знаю, поскольку XCode 4.4, @synthesize будет автоматически генерировать объекты доступа к свойствам. Но сейчас я прочитал образец кода о NSUndoManager, и в коде он заметил, что @synthesize добавлен явно. Как:

@interface RootViewController  ()

@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@property (nonatomic, strong) NSUndoManager *undoManager;

@end

@implementation RootViewController
//Must explicitly synthesize this
@synthesize undoManager;

Теперь я чувствую себя озадаченным... Когда я должен явно добавить @synthesize в свой код?

4b9b3361

Ответ 1

Там много ответов, но и большая путаница. Я постараюсь сделать какой-то заказ (или увеличить беспорядок, посмотрим...)

  • Прекратите говорить о Xcode. Xcode - это IDE. clang - компилятор . Эта функция, которую мы обсуждаем, называется автосинтезом свойств, а это расширение Objective-C, поддерживаемое clang, которое является компилятором по умолчанию, используемым Xcode.
    Просто, чтобы было ясно, если вы переключитесь на gcc в Xcode, вы не сможете воспользоваться этой функцией (независимо от версии Xcode). Точно так же, если вы используете текстовый редактор и компилируете с помощью clang из командной строки, вы будет.

  • Спасибо автосинтезу, вам не нужно явно синтезировать свойство, поскольку оно будет автоматически синтезировано компилятором как

    @synthesize propertyName = _propertyName
    

    Однако существуют несколько исключений:

    • свойство readwrite с пользовательским getter и setter

      при предоставлении обеих выборочной реализации getter и setter, свойство не будет автоматически синтезировано

    • свойство readonly с пользовательским getter

      при предоставлении пользовательской реализации getter для свойства readonly это не будет автоматически синтезировано

    • @dynamic

      при использовании @dynamic propertyName свойство не будет автоматически синтезировано (довольно очевидно, поскольку @dynamic и @synthesize являются взаимоисключающими)

    • свойства, объявленные в @protocol

      при соответствии протоколу любое свойство, определяемое протоколом, не будет автоматически синтезировано

    • свойства, объявленные в категории

      это случай, когда директива @synthesize не будет автоматически вставлена ​​компилятором, но эти свойства также не могут быть синтезированы вручную. Хотя категории могут объявлять свойства, они не могут быть синтезированы вообще, так как категории не могут создавать ивары. Ради полноты я добавлю, что все еще возможно подделать синтез свойств с помощью Objective-C времени выполнения.

    • переопределенные свойства (новый, поскольку clang-600.0.51, отправка с Xcode 6, спасибо Marc Schlüpmann)

      когда вы переопределяете свойство суперкласса, вы должны явно его синтезировать

Стоит отметить, что синтезирование свойства автоматически синтезирует поддержку ivar, поэтому, если синтез свойств отсутствует, ivar также будет отсутствовать, если явно не объявлено.

За исключением трех последних случаев, общая философия заключается в том, что всякий раз, когда вы вручную указываете всю информацию о свойстве (реализуя все методы доступа или используя @dynamic), компилятор предполагает, что вы хотите полностью контролировать свойство и он отключит автосинтез на нем.

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

Ответ 2

Если вы явно не используете @synthesize, компилятор поймет ваше свойство таким же образом, если вы написали

@synthesize undoManager=_undoManager;

тогда вы сможете записать в свой код такие вещи, как:

[_undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter

Это обычное соглашение.

если вы пишете

@synthesize undoManager;

у вас будет:

[undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter

Лично я перестаю использовать @synthesize, так как он не является обязательным. Для меня единственной причиной использования @synthesize является привязка iVar к @property. Если вы хотите сгенерировать для него определенный getter и setter. Но в данном фрагменте кода нет iVar, я думаю, что этот @synthesize бесполезен. Но теперь я думаю, что новый вопрос: "Когда использовать iVar?", И у меня нет другого ответа, чем "никогда" для этого!

Ответ 3

Когда я должен явно добавить @synthesize в свой код?

Как правило, если это необходимо: вы, вероятно, никогда не столкнетесь с ситуацией, когда это необходимо.

В одном случае вам может показаться полезным.

Предположим, вы пишете как пользовательский getter, так и setter, но хотите, чтобы переменная экземпляра возвращала ее. (Для свойства атома это так же просто, как и желание настраиваемого сеттера: компилятор будет писать геттер, если вы укажете установщик для одноатомного свойства, но не атомного свойства.)

Рассмотрим это:

@interface MyObject:NSObject
@property (copy) NSString *title;
@end

@implementation MyObject

- (NSString *)title {
    return _title;
}
- (void)setTitle:(NSString *)title {
    _title = [title copy];
}

@end

Это не сработает, потому что _title не существует. Вы указали как getter, так и setter, поэтому Xcode (правильно) не создает для него переменную экземпляра базы данных.

enter image description here

У вас есть два варианта для его существования. Вы можете либо изменить @implementation на это:

@implementation MyObject {
    NSString *_title;
}

- (NSString *)title {
    return _title;
}
- (void)setTitle:(NSString *)title {
    _title = [title copy];
}

@end

Или измените его на это:

@implementation MyObject

@synthesize title = _title;

- (NSString *)title {
    return _title;
}
- (void)setTitle:(NSString *)title {
    _title = [title copy];
}

@end

Иными словами, хотя синтез для практических целей никогда не нужен *, его можно использовать для define переменных экземпляра свойств, когда вы предоставляете getter/setter. Вы можете решить, какую форму вы хотите использовать.

В прошлом я предпочитал указывать переменную экземпляра в @implementation {}, но теперь я думаю, что маршрут @synthesize является лучшим выбором, поскольку он удаляет избыточный тип и явно связывает переменную подстановки с свойством:

  • Измените тип свойства и измените тип переменной экземпляра.
  • Измените свой классификатор хранилища (например, сделайте его слабым, а не сильным или сильным, а не слабым) и изменится определитель хранилища.
  • Удалить или переименовать свойство, а @synthesize создаст ошибку компилятора. Вы не закончите с переменными экземплярами экземпляра.

* - Я знаю один случай, когда это было необходимо, относящееся к разделению функций по категориям в нескольких файлах. И я не удивлюсь, если Apple это исправит или даже уже имеет.

Ответ 4

ОК, когда вы создаете свойство...

@property NSString *name;

Xcode автоматически синтезирует iVar, как если бы вы написали...

@synthesize name = _name;

Это означает, что вы можете получить доступ к свойству с помощью...

self.name;
// or
_name;

Либо будет работать, но только self.name действительно использует методы доступа.

Существует только один раз, когда автосинтез не работает.

Если вы перепишете, но установщик И метод getter, вам нужно будет синтезировать iVar.

Вы в порядке, если вы просто переопределяете сеттер или просто переопределяете получателя. Но если вы это сделаете, то компилятор не поймет этого, и вам нужно будет синтезировать его вручную.

Как правило, хотя.

Не делайте iVars. Просто используйте свойство. Не синтезируйте его.

Ответ 5

Синтез свойств требуется, когда свойство объявляется в протоколе. Он не будет автоматически синтезироваться в интерфейсе реализации.

Ответ 6

Спасибо за разъяснение. У меня была аналогичная проблема.

@synthesize firstAsset, secondAsset, audioAsset;
@synthesize activityView;

Итак, теперь, прокомментировав их, я прошел и заменил каждое событие, например

self.firstAsset Кажется, я мог бы также использовать firstAsset, но мне кажется, что я слишком часто вижу "слишком".

Ответ 7

Xcode не требует явного объявления @synthesize.

Если вы не пишете @synthesize, это то же самое, что и делать:

@synthesize manager = _manager;

Пример кода мог быть старым. Скоро они будут обновлены.

Вы можете получить доступ к своим свойствам, например:

[self.manager function];

Это рекомендуемое Apple соглашение. Я следую за ним, и я рекомендую вам тоже!