Intereting Posts
Изменение идентификатора кнопки в строке панели навигации Невозможно ли создать UIViewController программно, не создавая представление? Формат 9999999 в 9999999 (запятая после каждой третьей цифры) с использованием NSNumberFormatter Добавить «…» в конце четвертой строки Недействительный NSTimer после изменения VC Преобразование потенциальных клиентов с помощью Salesforce sdk для iOS Разработка, запуск в симуляторах приложений iOS на hackintosh Как избежать переопределения функций в общих библиотеках? UIBarButtonItem игнорирует атрибуты заголовка, когда в UIToolBar в iOS 8 Создайте массив JSON и объект JSON в быстром iOS: Как получить сохраненные данные приложения изнутри UNNotificationServiceExtension? Что запускает UITableView для загрузки своих данных в первый раз? Можно ли использовать собственное сканирование кредитных карт iOS 8 в родном приложении? Что такое сохранение iVar и self.iVar в Obj-c? Ошибка приложения при доступе к первой статической переменной в классе

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

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

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], который не будет работать. Имеет смысл?

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