Intereting Posts
Swift 3 warning func collectionView метод экземпляра почти соответствует необязательному требованию Xcode UIWebView не меняет страницу с измененным URL-адресом Организуйте несколько NSURLSessionTasks Как использовать performSegue из класса UIView в swift 3 Доступ к многоканальным данным из MTAudioProcessingTap UIScrollView не работает с EXC_BAD_ACCESS Как вы показываете представление предупреждения для push-уведомлений, если приложение не находится на переднем плане или в фоновом режиме в iOS? setContentOffset в UIScrollView в правильном направлении Использование специального шрифта в Xcode iOS – лучший способ получить номера из NSString! (Геокоординаты) UITableView дважды прокручивается при нажатии UITextField, за которым следует UIDatePicker Xamarin iOS 10 WebView заморозить Как зарегистрировать UIView для повторного использования для заголовка заголовка UITable без использования nib потерянные пользовательские данные при обновлении tableView Как избежать необходимости вручную устанавливать размер UIPopoverController?

Странное назначение в синтезе

Я видел много кода, подобного этому

header.h

@interface Foo : NSObject { NSString *str; } @property(nonatomic, retain) NSString *str; @end 

а затем в реализации

 @implementation Foo @synthesize str = _str; @end 

Я не могу понять, в чем преимущество использования такого задания?

 @synthesize str = _str; 

Это просто обычное соглашение об именах.

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

Если вы попытаетесь получить доступ к str в своем коде, например [str length], код не будет компилироваться. Вам либо нужно выполнить [self.str length], либо [_str length].

… и поскольку это неизменяемое свойство NSString, используйте copy , а не retain .

@synthesize str = _str; будет означать, что переменная экземпляра, которая синтезируется для свойства str называется _str . Поэтому в коде у вас есть несоответствие между ним и объявленной переменной экземпляра. Таким образом, на самом деле вы получите две переменные экземпляра, одну из которых называется str а одна – _str .

Вы хотите сделать это:

 @interface Foo : NSObject @property(nonatomic, retain) NSString *str; @end @implementation Foo @synthesize str = _str; @end 

Или это:

 @interface Foo : NSObject { NSString *str; } @property(nonatomic, retain) NSString *str; @end @implementation Foo @synthesize str; @end 

Или, очевидно, переименуйте объявленную переменную экземпляра _str .

На SO уже много вопросов о том, следует ли префикс с такими именами имен префикса, как подчеркивание в Objective C.

Вот краткий пример того, как полезно использовать изменение имени:

 @interface MyClass : NSObject { NSString *myString; } @property (nonatomic, retain) NSString *myString; - (NSString *)stringTreatment:(NSString *)str; @end @implementation MyClass @synthesize str = _str; - (id)init { self = [super init]; if (self) { self.str = [NSString string]; } return self; } - (NSString *)stringTreatment:(NSString *)str { return [str uppercaseString]; } @end 

Если бы вы не синтезировали str как _str, вы получили бы предупреждение в методе stringTreatment, заявив, что локальное объявление str скрывает переменную экземпляра.

Кроме того, в вашем коде вы можете назначить значение _str и получить вызов внешнего класса [MyClass str], и он вернет его.

Итак, чтобы сделать длинную историю короткой, «str» остается именем вашего свойства, а «_str» является внутренней ссылкой на это свойство. Например, вы не сможете использовать [MyClass _str], который не будет работать. Имеет смысл?

Надеюсь это поможет.