Swift UINavigationController子类中的强制init重写 [英] Mandatory init override in Swift UINavigationController subclass

查看:239
本文介绍了Swift UINavigationController子类中的强制init重写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在为服务于视图控制器流(以某种方式,例如UIImagePickerController做)的框架将UINavigationController子类化

I'm currently subclassing a UINavigationController for a framework that serves a view controller flow (in a way, like UIImagePickerController do)

这是我的实现示例,可以简化为可以在操场上运行.

Here's an example of my implementation, reduced to be as simple as possible, that can be run in a playground.

import UIKit

public class MyNavigationController: UINavigationController {

    public var anyVar: Int?

    public init(anyVar: Int) {
        let viewController = UIViewController()
        super.init(rootViewController: viewController)

        self.anyVar = anyVar
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

let navigationController = MyNavigationController(anyVar: 42)

最后一行崩溃了,并带有EXC_BAD_INSTRUCTION.当我在Xcode中运行时,它告诉我在运行时缺少init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?).

The last line is crashing, with a EXC_BAD_INSTRUCTION. When I run in Xcode, it's tells me at runtime that init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) was missing.

如果我重写该方法:

public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

...一切正常:您可以在自己的游乐场尝试.

...everything works well: you can try with your own playground.

我不明白为什么.对我来说这听起来不合逻辑.

I can't understand why. It doesn't sounds logic to me.

UIViewController文档说:

如果您将UIViewController子类化,则必须调用此方法的超级实现 方法,即使您未使用NIB. (为方便起见,默认的init方法将为您完成此操作, 并为这两个方法参数都指定nil.)

If you subclass UIViewController, you must call the super implementation of this method, even if you aren't using a NIB. (As a convenience, the default init method will do this for you, and specify nil for both of this methods arguments.)

但是我的init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)覆盖从super.init(rootViewController: viewController)初始化中被调用!
在不覆盖它的情况下,我猜应该调用UIViewController的init(nibName:bundle:),而不是.

But my init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) override gets called, from super.init(rootViewController: viewController) initialization!
Without overriding it, I guess the UIViewController's init(nibName:bundle:) should be called, but not.

我仍然不明白为什么重写方法并调用super会使程序更好地工作. IMO,仅调用super.thisMethod时覆盖方法是完全没有用的,它仅在调用堆栈中添加了方法调用.

I still cannot understand why overriding the method and calling super make the program works better. IMO, overriding a method while only calling super.thisMethod is totally useless, it only adds a method call in the call stack.

我必须缺少一些有关Swift初始化方法的要点,但我不知道要做什么.

I must missing something essentials about Swift init methods, but I can't figure out what.

推荐答案

之所以发生这种情况,是因为Swift继承初始化程序的方式.如果您在当前类中未声明任何初始化器,则编译器将从父类继承所有初始化器.但是,如果您覆盖/添加了新的初始化器(并使用init(anyVar:)进行了设置),Swift不会自动从父类继承初始化器,因此子类无法访问它们,这会导致运行时崩溃.

This is happening because of the way how Swift inherits initializers. If you don't declare any of initializers in current class the compiler will inherit all of the initializers from the parent class. But if you override/add new initializers (and you do it with init(anyVar:)) Swift will not automatically inherit initializers from parent classes, so they are not accessible from subclass which is leading to runtime crash.

如果您对超出此行为的原因感兴趣,可以查看中级Swift 部分和WWDC 2014(大约在34分钟左右的时间里,他们谈论的是初始化器继承)

If you are interested in reasons beyond this behavior you can check out Intermediate Swift section and WWDC 2014 (somewhere around 34-minute mark they are talking about initializers inheritance)

这篇关于Swift UINavigationController子类中的强制init重写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆