Ios 如何重写init-message而不在目标C中创建不需要的递归?

Ios 如何重写init-message而不在目标C中创建不需要的递归?,ios,objective-c,Ios,Objective C,我想使用自动设置图像、目标和选择器的初始值设定项对UIBarButtonItem进行子类化 我试图覆盖-(id)init消息,如下所示: - (id) init { self = [super initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(myMessage)]; if (self) { //Custom initialization

我想使用自动设置图像、目标和选择器的初始值设定项对UIBarButtonItem进行子类化

我试图覆盖
-(id)init
消息,如下所示:

- (id) init {
    self = [super initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(myMessage)];
    if (self) {
        //Custom initialization
    }
    return self;
}
- (id) init {
    self = [super initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(myMessage)];
    if (self) {
        //Custom initialization
    }
    return self;
}
这会导致不必要的递归,因为
initWithBarButtonSystemItem:target:action
调用
init

我阅读了以下问题的答案,但它没有帮助我,因为它仍然给我相同的递归:

我在测试时使用的代码如下:

- (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
  • 我不想使用标志来确定
    init
    是否已经运行过一次
我还想提到,我试图创建
UIBarButtonItem
,但没有使用
initWithBarButtonSystemItem:target:action
初始值设定项,但我找不到与第一个参数对应的
@属性


谢谢大家!

如您提供的链接中所述(参见已接受的答案),如果您使用
super
call初始化,则不会导致递归调用

也许你应该有这样的东西:

- (id) init {
    self = [super initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(myMessage)];
    if (self) {
        //Custom initialization
    }
    return self;
}
- (id) init {
    self = [super initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(myMessage)];
    if (self) {
        //Custom initialization
    }
    return self;
}

您可能会发现以下内容很有帮助:

特别要注意指定初始值设定项的概念:

+ (instancetype) bookmarksBarButtonItemWithAction:(SEL)action {
    return [[[self class] alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:action];
}
指定的初始值设定项对类起着重要作用。它确保通过调用超类的指定初始值设定项来初始化继承的实例变量。它通常是初始的。。。方法,该方法具有最多的参数,并执行大多数初始化工作,并且该类的二级初始化器通过向self发送消息来调用该初始化器

定义子类时,必须能够识别超类的指定初始值设定项,并通过发送给super的消息在子类的指定初始值设定项中调用它。您还必须确保以某种方式覆盖继承的初始值设定项。您可以根据需要提供尽可能多的方便初始值设定项。在设计类的初始值设定项时,请记住,指定的初始值设定项通过发送给super的消息相互链接;而其他初始值设定项通过消息self链接到其类的指定初始值设定项


这就是为什么你会看到这种行为
initWithBarButtonSystemItem:target:action
是该类的指定初始值设定项,它依次调用
init
。重写
init
调用指定的初始值设定项不会因为您描述的原因而改变

相反,您可以创建一个方便的构造函数来调用指定的初始值设定项:

+ (instancetype) bookmarksBarButtonItemWithAction:(SEL)action {
    return [[[self class] alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:action];
}

这将实现您想要的功能,甚至不需要您子类
UIBarButtonItem
。它可以作为一个类别来完成。

我知道你说过你不想要一个
initCustom
方法,但这是一个正确的解决方案。我知道这是一个Obj-C问题,但我建议你阅读Swift指南中关于。Swift将“指定”和“方便”初始值设定项的概念正式化,以避免此类问题。@rmaddy,这太令人失望了。@jtbandes,我来看看@用户1401083为什么?您希望实现一个特殊的
init
。给它起一个特别的名字是有意义的。默认的
init
有一定的含义。您需要另一个具有其他含义的
init
,因此请给它一个表示该含义的名称。正如我提到的,不幸的是,这对我不起作用。抱歉,我现在看到了差异,但这也没有帮助。感谢链接。但它没有回答我的问题。这让我更加困惑,因为他们举了一个例子,做了我正试图做的事情。我试图创建的初始化器类型称为方便初始化器,应该能够使用名称
init
。查看
任务
类的示例。我遗漏了什么吗?>“这就是为什么您会看到这种行为。initWithBarButtonSystemItem:target:action是该类的指定初始值设定项,它反过来调用init。重写init调用指定初始值设定项不会因为您所描述的原因。”