Насколько мне известно, начиная с 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
явно добавить в свой код?
@sythesize
. Если код все еще работает, то в этом нет необходимости.Ответы:
Ответов много, но есть большая путаница. Попробую навести какой-то порядок (или бардак увеличивать, посмотрим ...)
Перестанем говорить о Xcode. Xcode - это IDE . clang - это компилятор . Эта функция, которую мы обсуждаем, называется автосинтезом свойств, и это расширение языка Objective-C, поддерживаемое clang , который является компилятором по умолчанию, используемым Xcode.
Чтобы было ясно, если вы переключитесь на gcc в Xcode, вы не получите преимуществ от этой функции (независимо от версии Xcode). Точно так же, если вы используете текстовый редактор и компилируете с помощью clang из командной строки, вы будут.
Благодаря автосинтезу вам не нужно явно синтезировать свойство, поскольку оно будет автоматически синтезировано компилятором как
@synthesize propertyName = _propertyName
Однако есть несколько исключений:
readwrite свойство с настраиваемым получателем и сеттером
при обеспечении как геттер и сеттер пользовательской реализации, свойство не будет автоматически синтезированными
readonly свойство с настраиваемым получателем
при предоставлении пользовательской реализации геттера для свойства только для чтения это не будет автоматически синтезироваться
@dynamic
при использовании
@dynamic propertyName
свойство не будет автоматически синтезироваться (довольно очевидно, поскольку@dynamic
и@synthesize
являются взаимоисключающими)свойства, объявленные в @protocol
при согласовании с протоколом любое свойство, определяемое протоколом, не будет автоматически синтезировано
недвижимость, объявленная в категории
это случай, когда
@synthesize
директива не вставляется автоматически компилятором, но эти свойства также нельзя синтезировать вручную. Хотя категории могут объявлять свойства, их вообще нельзя синтезировать, поскольку категории не могут создавать ivars. Для полноты картины я добавлю, что еще можно подделать синтез свойств с помощью среды выполнения Objective-C .переопределенные свойства (новое с clang-600.0.51, доставка с Xcode 6, спасибо Marc Schlüpmann)
когда вы переопределяете свойство суперкласса, вы должны явно синтезировать его
Стоит отметить, что при синтезе свойства автоматически синтезируется резервный ivar, поэтому, если синтез свойства отсутствует, ivar также будет отсутствовать, если явно не объявлен.
За исключением последних трех случаев, общая философия заключается в том, что всякий раз, когда вы вручную указываете всю информацию о свойстве (путем реализации всех методов доступа или использования
@dynamic
), компилятор будет предполагать, что вам нужен полный контроль над свойством, и отключит автосинтез на Это.За исключением случаев, перечисленных выше, единственным другим
@synthesize
способом использования явного типа является указание другого имени ivar. Однако соглашения важны, поэтому я советую всегда использовать именование по умолчанию.источник
@synthesize
в категории это запрещено (как вы уже отметили, в категориях отсутствует ivar). Добавлю примечание.Если вы не используете явно,
@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
. Если вы хотите создать для него определенные геттеры и сеттеры. Но в данном куске кода нетiVar
, думаю, что это@synthesize
бесполезно. Но теперь я думаю, что новый вопрос - «Когда использоватьiVar
?», И у меня нет другого ответа, кроме «никогда» на этот!источник
@synthesize
как больше нет причин. Кроме того, начальное подчеркивание служит хорошим визуальным флажком, чтобы вы знали, что работаете с сетью безопасности управления памятью и потоками, которую обеспечивают свойства (которые вы должны пропуститьinit
иdealloc
методы).Когда я должен
@synthesize
явно добавить в свой код?Как правило, если это требуется: вы, вероятно, никогда не попадете в дело, где это необходимо.
Однако есть один случай, который может вам пригодиться.
Предположим, вы пишете как собственный метод получения, так и метод установки, но хотите, чтобы его поддерживала переменная экземпляра. (Для атомарного свойства это так же просто, как потребность в настраиваемом сеттере: компилятор напишет геттер, если вы укажете сеттер для одноатомного свойства, но не для атомарного свойства.)
Учти это:
@interface MyObject:NSObject @property (copy) NSString *title; @end @implementation MyObject - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
Это не сработает, потому
_title
что не существует. Вы указали и геттер, и сеттер, поэтому Xcode (правильно) не создает для него переменную резервного экземпляра.У вас есть два варианта, как заставить его существовать. Вы можете изменить на
@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
Другими словами, хотя для практических целей синтезировать никогда не требуется *, его можно использовать для определения переменных экземпляра, поддерживающих свойства, когда вы предоставляете геттер / сеттер. Вы можете решить, какую форму здесь вы хотите использовать.
Раньше я предпочитал указывать переменную экземпляра в
@implementation {}
, но теперь думаю, что@synthesize
маршрут - лучший выбор, поскольку он удаляет избыточный тип и явно связывает поддерживающую переменную со свойством:@synthesize
компилятор выдаст ошибку. Вы не получите случайных переменных экземпляра.* -Я знаю один случай, когда это было необходимо, относящееся к разделению функциональности по категориям в нескольких файлах. И я не удивлюсь, если Apple исправит это или даже уже исправит.
источник
atomic
он не был добавлен в качестве спецификатора свойства позже. Теперь, когда он там, вы можете найти предупреждающий флагCLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES
.Хорошо, когда вы создаете недвижимость ...
@property NSString *name;
Xcode автоматически синтезирует iVar, как если бы вы написали ...
@synthesize name = _name;
Это означает, что вы можете получить доступ к собственности с помощью ...
self.name; // or _name;
Любой из них будет работать, но на
self.name
самом деле использует только методы доступа.Автосинтез не работает только один раз: если вы перезаписываете, но сеттер И метод получения, тогда вам нужно будет синтезировать iVar.
У вас все в порядке, если вы просто переопределите установщик или просто переопределите получатель. Но если вы сделаете и то, и другое, компилятор этого не поймет, и вам придется синтезировать это вручную.
Тем не менее, как правило.
Не делайте iVars. Просто используйте свойство. Не синтезируйте это.
источник
Синтез свойств требуется, когда свойство объявляется в протоколе. Он не будет автоматически синтезироваться в интерфейсе реализации.
источник
Спасибо, что разъяснили это. У меня была аналогичная проблема.
@synthesize firstAsset, secondAsset, audioAsset; @synthesize activityView;
Итак, теперь, закомментировав их, я просмотрел и заменил каждое вхождение, например,
self.firstAsset Кажется, я мог бы также использовать firstAsset, но обнаружил, что слишком часто скучаю по значку " ".
источник
Xcode не требует явного
@synthesize
объявления.Если вы не пишете,
@synthesize
это то же самое, что и делать:@synthesize manager = _manager;
Образец кода мог быть старым. Скоро они его обновят.
Вы можете получить доступ к своим свойствам, например:
[self.manager function];
Это рекомендованное Apple соглашение. Я слежу за ним и рекомендую вам тоже!
источник
[_manager function]
НЕ будет обращаться к свойству, вместо этого он будет напрямую обращаться к базовому ivar .[_manager function]
не использует аксессоры свойства.