Ответ 1
Самый идиоматический способ справиться с этой ситуацией - просто удалить свою декларацию delegate
ivar. Если вы использовали ваш delegate
ivar, вместо него следует использовать неявный ivar _delegate
.
Почему это работает?
Начиная с Xcode 4.4 (LLVM Compiler 4.0), переменные экземпляра и методы доступа автоматически синтезируются для свойства, если директива @synthesize
не используется явно для этого имущество. Как документация Apple по инкапсуляции заявляет
По умолчанию [...] методы доступа автоматически синтезируются для вас компилятором, поэтому вам не нужно ничего делать, кроме объявления свойства, используя @property в интерфейсе класса.
Ивар, который используется для свойства (который получен и установлен с помощью методов автоматического доступа к синтезированным свойствам), называется _<propertyName>
(то есть имя ivar - это имя свойства с префиксом подчеркивания).
В этом случае имя свойства delegate
, поэтому используемый ivar - _delegate
. Это уже происходит в вашем коде. Когда вы вызываете -delegate
и -setDelegate:
, этот ivar _delegate
будет получен и установлен.
Однако вы также объявили свой собственный ivar delegate
. Конечно, ивар, который вы явно объявили (delegate
), не будет получен и установлен с помощью методов экземпляра -delegate
и -setDelegate:
, поскольку автоматически сгенерированный ivar (_delegate
) будет получен и установлен. Однако (почти всегда - если бы это было не так, ваш код был неоднозначным), ваше намерение заключалось в том, что ваш ivar delegate
будет тем, что ваши аксессуры вашей собственности будут получать и устанавливать. К счастью, компилятор достаточно умен, чтобы заметить, что вы сделали, и почему он испускает это предупреждение:
warning: autosynthesized property '
delegate
' будет использовать синтезированную переменную экземпляра '_delegate
', а не существующую переменную экземпляра 'delegate
' [-Wobjc-autosynthesis-property-ivar-name-match
]
Сообщая вам, что ваше свойство delegate
будет использовать автоматически синтезированный ivar _delegate
, а не ivar, который вы явно объявили, delegate
.
Итак, если вы просто удалите свой delegate
ivar, компилятор прекратит выдавать это предупреждение. Если вы использовали delegate
ivar напрямую (не через свойство), начните использовать _delegate
вместо этого.
Небольшая вариация этой опции заключается в явном объявлении того же ivar (_delegate
), что создается автоматический синтез свойства delegate
. Вы можете сделать это, заменив
@interface TheClass : TheSuperclass
{
//...
id<TheDelegateProtocol> delegate
//...
}
@end
с
@interface TheClass : TheSuperclass
{
//...
id<TheDelegateProtocol> _delegate
//...
}
@end
Это работает, потому что автоматический синтез свойства всегда будет использовать ivar, чье имя является именем свойства с префиксом подчеркивания. Если такой ivar не существует, будет создан ivar. Если он существует, он будет использоваться.
Если вместо этого вы предпочтете, чтобы ваши аксессоры свойств были установлены и получили ваш ivar delegate
, вы можете добавить директиву @synthesize
к вашему классу '@implementation
, чтобы сообщить компилятору сделать именно это:
@implementation TheClass
//...
@synthesize delegate = delegate;
//...
@end
Строка @synthesize delegate = delegate;
сообщает компилятору использовать ivar delegate
(правую часть назначения) в аксессуарах для свойства delegate
(левая сторона задания).
Вы также можете опустить правую сторону назначения @synthesize
и просто написать
@implementation TheClass
//...
@synthesize delegate;
//...
@end
Это работает, потому что свойство с ручным @synthesize
, которое явно не указывает, что ivar, которое должно быть получено и установлено его аксессуарами (например, @synthesize delegate;
), будет использовать ivar с тем же именем, что и свойство, NOT prefixed под знаком подчеркивания. Это связано с обратной совместимостью.