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

时间:2013-01-06 17:22:18

标签: objective-c

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

  

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

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

2 个答案:

答案 0 :(得分:39)

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

为什么这样做?

Xcode 4.4 (LLVM Compiler 4.0)开始,如果@synthesize指令未明确用于该属性,则会自动为属性合成实例变量和访问器方法。正如Apple's documentation on encapsulation

  

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

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

在这种情况下,属性名称为delegate,因此使用的ivar为_delegate。这已经在你的代码中发生了。当您致电-delegate-setDelegate:时,将获取并设置此ivar _delegate

但是,您也宣布了自己的ivar delegate。当然,由于自动合成的ivar(delegate)正在进行,因此实例方法-delegate-setDelegate:将不会获取和设置您明确声明的{_delegate)的ivar。得到并设定。然而,(几乎总是 - 如果不是,你的代码是模棱两可的)你的意图是你的ivar delegate成为你的财产的访问者将获得和设置的东西。幸运的是,编译器足够聪明地注意到你已经完成了什么,这就是它发出这个警告的原因:

  

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

它告诉您,您的属性delegate将使用自动合成的ivar _delegate,而不是您明确声明的ivar delegate

因此,如果您只是删除delegate ivar,编译器将停止发出此警告。如果您直接使用delegate ivar(而非通过该属性),请改为使用_delegate


此选项的一个小变化是显式声明_delegate属性的自动合成正在创建的相同ivar(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;告诉编译器在属性delegate的访问器中使用ivar delegate(赋值的右手)(赋值的左侧)

您也可以省略@synthesize作业的右侧,只需编写

@implementation TheClass
//...
@synthesize delegate;
//...
@end

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

答案 1 :(得分:2)

还有另一种方法,这个方法对我有用:

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

然后,您可以将此添加到实现中而不会出现错误:

@synthesize delegate;

另外:这符合ARC标准。