最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】Swift创建页面代码super.init(nibName: nil, bundle: nil)和required init?(coder aDecoder: NSCoder)的含义

Swift crifan 5093浏览 0评论

【背景】

想要搞清楚,用Swift去创建页面时,看到别人用的代码:

    init() {
        super.init(nibName: nil, bundle: nil)
    }
   
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

是什么含义。

【解决过程】

1.搜:

swift super.init(nibName: nil, bundle: nil)

swift required init?(coder aDecoder: NSCoder)

参考:

Initializing View Controllers in Swift · The Main Thread

ios – Swift: Class does not implement its superclass’s required members – Stack Overflow

NSCoder and swift initialization

Swift 类构造器的使用

Swift Initializer Confusion – TIL by Ed

Swift子类,默认情况下,不会继承父类的构造器(初始化函数)

2.搜:

swift Automatic Initializer Inheritance

参考:

The Swift Programming Language (Swift 2): Initialization

好好看看其中的:

Class Inheritance and Initialization

部分的内容。

3.Swift中初始化的话:

首先要说个前提,

Swift为了安全,所以要保证,一个类中(所保存的)所有的变量(属性),

(包括子类从父类中继承的所有的属性变量)

都要在初始化的时候,就设置一个值

即:

保证所有属性变量都有个初始化值

(避免有些人写代码不小心,漏初始化了,导致后续代码出错)

而Swift,之所以把一个,本来很简单的init初始化的机制,搞得这么麻烦,就是为了实现:

这种机制,可以保证所有的变量都有初始化值

4.什么机制呢,就是:

Swift中,对于初始化函数,此处一般翻译为:构造器

有两种:

  • designated initializers==此处翻译为:指定构造
    • 初始化当前子类中所有的变量,并且还要调用父类的指定构造器
    • 是一个类的,主要,构造器。
    • 一个类中,一般只有一个,至少也要有一个 指定构造器。
      • 有时候会有,子类从父类继承多个指定构造器的情况。
  • convenience initializers==此处翻译为:方便构造器
    • 是一个类的,次要的,辅助的,构造器;
    • 一个类中,有可能没有,也可能有多个,方便构造器。
    • 方便构造器,最终都还是要调用到 指定构造器
    • 方便构造器,可以调用同类中的指定构造器

指定构造器和方便构造器的语法:

	init(parameters) {	
    statements
}

	convenience init(parameters) {	
    statements
}

5.指定构造器和方便构造器之间的关系,可以用下图示意:

designated convenience initializer pass througn

 

“便利构造器是类的次要构造器, 你需要让便利构造器调用同一个类中的指定构造器, 并将这个指定构造器中的参数填上你想要的默认参数.

如果你的类不需要便利构造器的话, 那么你就不必定义便利构造器, 便利构造器前面必须加上 convenience 关键字.”

 

去看了对应的UIViewController的函数原型,其中找到了:

    /*
      The designated initializer. 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.) In the specified NIB, the File's Owner proxy should
      have its class set to your view controller subclass, with the view outlet connected to the main view. If you
      invoke this method with a nil nib name, then this class' -loadView method will attempt to load a NIB whose
      name is the same as your view controller's class. If no such NIB in fact exists then you must either call
      -setView: before -view is invoked, or override the -loadView method to set up your views programatically.
    */
    public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
    public init?(coder aDecoder: NSCoder)

所以,对应的,此处子类,去继承UIViewController的子类,才要去实现父类中的designated initializer,然后初始化值都是nil,所以才写成:

super.init(nibName: nil, bundle: nil)

 

看了:

Swift 类构造器的使用

基本明白了init的初始化逻辑和注意事项。

 

但是还没有完全搞懂那个:

required init?

的含义。

继续看官网的:

The Swift Programming Language (Swift 2): Initialization

中关于required init的解释。

父类中,定义了一个 制定构造器,加上required后:

	class SomeClass {
	required init() {
	// initializer implementation goes here
	}
}

表示:

子类中必须要实现这个required init

并且子类的写法,也是:

	class SomeSubclass: SomeClass {
	required init() {
	// subclass implementation of the required initializer goes here
	}
}

而不是写override

同时,子类的子类,也必须要实现这个required init。

所以此处的required init,就只是继承实现了父类的required init而已。

暂时无需太关心。

【总结】

至此,基本明白了:

    init() {
        super.init(nibName: nil, bundle: nil)
    }

是当前子类的制定构造器。

并且要在初始化子类自己的所有的变量之后,再去调用父类的init。

具体的init的参数,取决于所继承的父类(可以通过看父类的源码而得知)

以及初始化参数,一般无需太操心时,往往都是nil

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

是实现了,父类中的required init而已。

其内部实现,继续只是调用父类的init而已。没啥特殊的。

转载请注明:在路上 » 【已解决】Swift创建页面代码super.init(nibName: nil, bundle: nil)和required init?(coder aDecoder: NSCoder)的含义

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
84 queries in 0.188 seconds, using 22.10MB memory