如何覆盖init-message而不在Objective C中创建不需要的递归?

时间:2014-07-29 21:43:48

标签: ios objective-c

我希望使用自动设置图像,目标和选择器的初始化程序将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

谢谢!

2 个答案:

答案 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。它可以作为一个类别来完成。