Подтвердить что ты не робот

Autosynthesized property 'delegate' будет использовать синтезированную переменную экземпляра '_delegate', не существующую переменную экземпляра 'delegate'

Я следую руководству здесь, чтобы создать пользовательский делегат. Он работает нормально, но я получаю следующее предупреждение в xcode

DetailViewController.m: 23: 1: Autosynthesized свойство 'delegate' будет использовать синтезированную переменную экземпляра '_delegate', не существующий экземпляр переменная 'delegate'

Может ли кто-нибудь посоветовать, как избавиться от предупреждения

4b9b3361

Ответ 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 под знаком подчеркивания. Это связано с обратной совместимостью.

Ответ 2

Там был еще один метод, и этот работал у меня:

@property (nonatomic, unsafe_unretained) id <MyDelegate> delegate;

Затем вы можете добавить это в реализацию без ошибок:

@synthesize delegate;

Также: это совместимо с ARC.