在Objective-C中自定义init方法,如何避免递归?

Phi*_*ert 3 iphone cocoa-touch objective-c init uikit

我想创建一个UINavigationController的子类,它总是以相同的根控制器开始.没什么特别的,所以(对我来说)覆盖这样的init方法是完全合理的:

- (id) init {
   rootController = [[MyController alloc] init];

   if (self = [super initWithRootViewController:rootController]) {
       // do some more initialization
   }

   return self;
}
Run Code Online (Sandbox Code Playgroud)

这显然会产生一个问题,因为[super initWithRootViewController]将调用[UINavigationController init],这当然是我们重写的init方法,因此将发生无限递归.

我不想创建一个名为"initCustom"的不同名称的init方法.

目前我只能提出一个解决方案,但我真的讨厌这种黑客攻击:

- (id) init {
   if (initCalled)
       return self;

   initCalled = YES;

   rootController = [[MyController alloc] init];

   if (self = [super initWithRootViewController:rootController]) {
       // do some more initialization
   }

   return self;
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:有更好的方法来处理这个问题吗?我确定我错过了一些非常明显的东西,但我没有看到它.

编辑:我想这样做的原因,我可以在下面的评论中看到:

我想创建一个始终以特定视图控制器开始的导航控制器.我想把这个隐藏在班级的消费者手中.无需暴露不需要暴露的东西.让生活变得更轻松,编码更清晰(封装发明的原因之一,对吧?)

gca*_*amp 10

首先,UINavigationController不用于子类化.

无论如何,最简单的方法是覆盖 initWithRootViewController:

- (id) initWithRootViewController:(UIViewController) viewController {
   return [super initWithRootViewController:[[[MyController alloc] init] autorelease]];
}
Run Code Online (Sandbox Code Playgroud)

你最好不要自动释放MyController,但你理解这个想法......

  • 来自文档'这个类不用于子类.相反,在希望应用程序的用户界面反映内容的层次性的情况下,可以按原样使用它的实例.这意味着Apple可以随时改变内部行为.(只是子类'init'也不错,对于硬核子类来说更多) (5认同)