我希望使用自动设置图像,目标和选择器的初始化程序将UIBarButtonItem
子类化。
我试图像这样覆盖- (id) init
消息:
- (id) init {
self = [super initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(myMessage)];
if (self) {
//Custom initialization
}
return self;
}
这会导致意外的递归,因为initWithBarButtonSystemItem:target:action
会调用init
。
我阅读了以下问题的答案,但它没有帮助我,因为它仍然给我相同的递归: Custom init method in Objective-C, how to avoid recursion?
我在测试时使用的代码如下:
- (id)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(id)target action:(SEL)action {
return [super initWithBarButtonSystemItem:systemItem target:target action:action];
}
- (id) init {
self = [self initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(myMessage)];
if (self) {
//Custom initialization
}
return self;
}
我与上述问题的作者有相同的要求:
- (id) initCustom
这样的自定义初始化。init
是否已经运行过一次。我还想提一下,我尝试在不使用UIBarButtonItem
初始化程序的情况下创建initWithBarButtonSystemItem:target:action
- 但我找不到与第一个参数对应的@property
。
谢谢!
答案 0 :(得分:0)
正如您提供的链接中所述(请参阅接受的答案),如果您使用super
调用初始化,则不会导致递归调用。
可能你应该有这样的事情:
- (id) init {
self = [super initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(myMessage)];
if (self) {
//Custom initialization
}
return self;
}
答案 1 :(得分:0)
您可能会发现这有用:Concepts in Objective-C: Object Initialization
特别要注意指定初始化程序的概念:
指定的初始值设定项在类中起着重要作用。它确保通过调用超类的指定初始化程序来初始化继承的实例变量。它通常是init ...方法,它具有最多的参数并且执行大部分初始化工作,并且它是初始化程序,类的辅助初始化程序使用消息调用self。
定义子类时,必须能够识别超类的指定初始化程序,并通过消息指向子类的指定初始化程序。您还必须确保以某种方式覆盖继承的初始值设定项。您可以根据需要提供尽可能多的便利初始化程序。在设计类的初始化程序时,请记住指定的初始化程序通过消息链接到super;而其他初始化器通过自己的消息链接到他们班级的指定初始化器。
这就是您看到此行为的原因。 initWithBarButtonSystemItem:target:action
是该类的指定初始值设定项,它依次调用init
。由于您所描述的原因,覆盖init
以呼叫指定的初始化程序不会获胜。
相反,您可以创建一个调用指定初始值设定项的便捷构造函数:
+ (instancetype) bookmarksBarButtonItemWithAction:(SEL)action {
return [[[self class] alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:action];
}
这几乎可以实现您所寻找的目标,甚至不需要您继承UIBarButtonItem
。它可以作为一个类别来完成。