我正在按照指南here创建自定义委托。它运行正常,但我在xcode中收到以下警告
DetailViewController.m:23:1:自动合成属性'委托'将 使用合成的实例变量'_delegate',而不是现有的实例 变量'委托'
任何人都可以建议如何摆脱警告
答案 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标准。