自动合成属性'委托'将使用合成的实例变量'_delegate',而不是现有的实例变量'委托'

tot*_*ian 17 objective-c

我正在按照此处的指南创建自定义委托.它运行正常,但我在xcode中收到以下警告

DetailViewController.m:23:1:Autosynthesized属性'委托'将使用合成的实例变量'_delegate',而不是现有的实例变量'delegate'

任何人都可以建议如何摆脱警告

Nat*_*ler 39

处理这种情况最惯用的方法就是删除你的delegateivar声明.如果您使用的是delegateivar,则应使用隐式ivar _delegate.

为什么这样做?

Xcode 4.4(LLVM编译器4.0)开始,如果@synthesize未对该属性明确使用该指令,则会自动为属性合成实例变量和访问器方法.作为Apple关于封装状态的文档

默认情况下,编译器会自动为您合成访问器方法,因此除了在类接口中使用@property声明属性之外,您无需执行任何操作.

用于属性的ivar(由自动合成的属性访问器方法获取和设置)被命名_<propertyName>(即,ivar的名称是以下划线为前缀的属性名称).

在这种情况下,属性名称是delegate,因此使用的是ivar _delegate.这已经在你的代码中发生了.当你调用-delegate-setDelegate:,这伊娃_delegate将得到和设置.

但是,你也宣布了自己的伊娃delegate.当然,你明确声明(delegate)的ivar 不会被实例方法获取-delegate和设置,-setDelegate:因为自动合成的ivar(_delegate)被获取并设置.然而,(几乎总是 - 如果不是,你的代码是模棱两可的)你的意图是你的ivar delegate成为你的财产的访问者得到和设置的东西.幸运的是,编译器足够聪明,可以注意到你做了什么,这就是它发出这个警告的原因:

警告:autosynthesized属性' delegate'将使用合成的实例变量' _delegate',而不是现有的实例变量' delegate'[ -Wobjc-autosynthesis-property-ivar-name-match]

它告诉你,你的财产delegate将使用自动合成的ivar _delegate而不是你明确声明的ivar delegate.

因此,如果您只是删除您的delegateivar,编译器将停止发出此警告.如果您delegate直接使用ivar(而不是通过酒店),请_delegate改为开始使用.


此选项的一个小变化是显式声明属性_delegate的自动合成delegate正在创建的相同ivar().您可以通过替换来完成此操作

@interface TheClass : TheSuperclass
{
    //...
    id<TheDelegateProtocol> delegate
    //...
}
@end
Run Code Online (Sandbox Code Playgroud)

@interface TheClass : TheSuperclass
{
    //...
    id<TheDelegateProtocol> _delegate
    //...
}
@end
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为属性的自动合成将始终使用ivar,其名称是以下划线为前缀的属性名称.如果不存在这样的ivar,将生成ivar.如果确实存在,将使用它.


如果您希望您的属性的访问器设置并获取您的ivar,delegate您可以@synthesize向您的类添加一个指令' @implementation告诉编译器执行此操作:

@implementation TheClass
//...
@synthesize delegate = delegate;
//...
@end
Run Code Online (Sandbox Code Playgroud)

该行@synthesize delegate = delegate;告诉编译器delegate在属性的访问器中使用ivar (赋值的右手)delegate(赋值的左侧).

您也可以省略作业的右侧@synthesize并写入

@implementation TheClass
//...
@synthesize delegate;
//...
@end
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为具有手册的属性@synthesize没有明确指定由其访问器(例如@synthesize delegate;)获取和设置的ivar将使用与属性同名的ivar,而不是以下划线为前缀.这与向后兼容性有关.

  • 另一种选择是删除实例变量,让编译器自动为您创建.除非你做一些特别的事情,否则你不应该自己申报. (6认同)