Что означает это предупреждение о значении свойств objective-c?
Начиная с обновления до Xcode 5.1, я начинаю видеть следующее предупреждение в некотором коде, используемом моим проектом. Я пытаюсь понять, что это значит.
Предупреждение: Auto property synthesis will not synthesize property 'responseHeader' because it is 'readwrite' but it will be synthesized 'readonly' via another property
Код, в котором он встречается, в файле .m:
@interface S3Response ()
@property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
@end
Предыдущее объявление свойства в файле .h:
@property (nonatomic, readonly) NSDictionary *responseHeader;
Для этого свойства нет инструкции @synthesize
, а также responseHeader
или setResponseHeader
, определенные как методы. Однако существует четкое определение ivar с именем responseHeader
.
Мне кажется довольно простым: свойство объявляется как доступное только для пользователей класса, но локально читается и записывается, поэтому класс может его установить.
Что означает это предупреждение, и что мне с этим делать?
Ответы
Ответ 1
Этот код, как представляется, из AWS SDK для iOS,
и S3Response
является подклассом AmazonServiceResponse
.
Открытый AmazonServiceResponse
интерфейс определяет свойство только для чтения
@interface AmazonServiceResponse:NSObject
// ...
@property (nonatomic, readonly) NSDictionary *responseHeader;
@end
который переопределяется как чтение и запись в расширении класса в файле реализации:
@interface AmazonServiceResponse ()
@property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
@end
Теперь подкласс S3Response
также хочет получить доступ на чтение и запись к этому свойству,
и поэтому также определяет в расширении класса его файл реализации:
@interface S3Response ()
@property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
@end
Компилятор жалуется, потому что - при компиляции "S3Response.m" - он не знает
что сеттер для свойства существует в суперклассе (он не читает
файл реализации суперкласса в этой точке). Также компилятор не может
просто синтезируйте сеттер в подклассе, потому что он не может не знать, что
свойство резервируется переменной экземпляра в суперклассе.
Но вы знаете, что сеттер будет сгенерирован, поэтому вы можете удалить предупреждение
добавление объявления @dynamic
в реализацию подкласса:
@implementation S3Response
@dynamic responseHeader;
...
@dynamic
является "обещанием" компилятору, что все необходимые методы доступа будут
быть доступным во время выполнения.
Ответ 2
Проблема здесь заключается в следующем.
По умолчанию, если вы не произвольно записываете право собственности (слабый/сохраняете/сильный/назначать), xCode будет автоматически проверять тип. Поэтому в случае NSDictionary он будет сильным. Таким образом, в интерфейсе вы будете иметь
@property (nonatomic, readonly, strong) NSDictionary *responseHeader;
Тогда это будет противоречить вашему определению частной реализации
@property (nonatomic, readwrite, retain) NSDictionary *responseHeader;
Компилятор не соответствует сильным и сохраняется при синтезе свойств, хотя формально это одно и то же.
Чтобы вылечить ситуацию, вы можете записать сохранение в обоих случаях или, вернее, не писать вообще. Он будет сильным по умолчанию в обоих определениях.