2

我将 UIToolbar 子类化,因为我将在我的应用程序中重用它。UIToolbar 使用委托协议:

//
// UIToolbarCustom.h
//

#import <UIKit/UIKit.h>

@protocol UIToolbarCustomDelegate

@required
- (void)tab:(UIBarButtonItem *)sender;
- (void)ok:(UIBarButtonItem *)sender;

@end

@interface UIToolbarCustom : UIToolbar {

    id <UIToolbarCustomDelegate> delegate;

}

@property (strong, nonatomic) id delegate;

@end

斯坦福 iOS 开发课程老师建议显式声明所有 ivars 前缀,如下划线,例如:

@implementation UIToolbarCustom

@synthesize delegate = _delegate;

@end

但是,在这个指定的场景中,它给了我一个错误:

error: property 'delegate' attempting to use ivar '_delegate'...

如果我使用,代码工作得很好:

 @synthesize delegate = __delegate; or
 @synthesize delegate;

这里发生了什么?UIToolbar 类中是否有一个名为 _delegate 的私有实例变量?

更新

感谢大家的所有澄清和建议,我学到了很多东西。原来我是 iOS 开发的新手(这是我的第一个应用程序的第二个版本,所以我正在努力做正确的事=p)。按照提示,我提出了这个新的头文件:

//
// Toolbar.h
//

#import <UIKit/UIKit.h>

@protocol ToolbarDelegate

@required
- (void)tab:(UIBarButtonItem *)sender;
- (void)ok:(UIBarButtonItem *)sender;

@end

@interface Toolbar : UIToolbar

@property (strong, nonatomic) id delegate;

@end

笔记:

  1. 类前缀已删除。

  2. 委托声明已被删除(我使用的是 ios 委托教程代码,但代码示例使用的是较旧的 xcode 版本,需要声明)。

  3. 合成被移除了,我也不知道我们不再需要合成我们的属性了。

PS:显然代码不起作用,因为ivar问题。我要改名字,所以不用合成,反正也不知道用什么名字……

4

2 回答 2

5

这里发生了什么?UIToolbar 类中是否有一个名为 _delegate 的私有实例变量?

是的,这正是问题所在。您需要为您的实例变量提供一个不同的名称。__delegate将起作用,或者您可以在名称前加上 3 个字母前缀(见最后一段)。

请注意,您已将 ivar 声明为delegate,然后在 synthesize 语句中告诉编译器使用_delegate. 实际上,这意味着您的delegateivar 根本没有被使用。在任何情况下,如果您正在为 iOS(而不是 32 位 Mac)编写代码,就像您一样,您不需要在子类的 @interface 部分中显式声明实例变量,因为编译器会自动为你。

最后,将您自己的子类命名为以“UI”开头的名称是不好的形式,因为 UI 前缀是为属于 UIKit 的类保留的。您应该使用自己的 3 个字母前缀,否则根本没有前缀。问题是未来版本的 UIKit 可能会包含一个名为“UIToolbarCustom”的类,而您的子类会与它发生冲突。

于 2013-01-07T21:51:05.480 回答
1

自从去年 Xcode 4.3 出来之后,你就不需要综合你的属性了。它由编译器为您完成(生成一个 ivar,并在其名称中添加前导下划线)。这意味着您也不需要声明 ivar。如果这样做,请务必将其命名为_delegate.

所以,你真正需要的是这一行:

@property (strong, nonatomic) id<UIToolbarCustomDelegate> delegate;

更新:请参阅Andrew Madsen 的完整故事答案。原来 UIToolbar 有自己的名为_delegate. 谁知道!

于 2013-01-07T21:51:23.750 回答