天天看点

Swift - 重写UIKit框架类的init初始化方法(以UITabBarController为例)

原来写了篇文章讲UITabBarController的用法,当时是从UIViewController跳转到UITabBarController页面,代码如下:

1

​self​

​​

​.presentViewController(​

​MainTabViewController​

​(), animated:​

​true​

​, completion:​

​nil​

​)​

有网友问:如果跳转的时候想给UITabBarController传递参数,要如何实现?

方法1:可以给UITabBarController实例对象的内部变量赋值

2

3

4

5

6

7

8

9

10

11

12

​let​

​ ​

​tabController = ​

​MainTabViewController​

​()​

​tabController.param = ​

​"这个是传递的参数"​

​self​

​.presentViewController(tabController, animated:​

​true​

​, completion:​

​nil​

​)​

​class​

​MainTabViewController​

​:​

​UITabBarController​

​{    ​

​var​

​param:​

​String​

​?​

​override​

​func​

​viewDidLoad()​

​{       ​

​}​

​}​

但如果我们想要在页面初始化的时候就要用到这个参数,比如viewDidLoad()中。那么就要考虑下一种方法,在初始化方法中进行参数传递。 

方法2:重写init初始化构造函数实现参数传递

对于UIKit框架类,不能像下面一样简单的重写:

​class​

​MainTabViewController​

​:​

​UITabBarController​

​{    ​

​var​

​param:​

​String​

​?​

​init​

​(param: ​

​String​

​) {​

​self​

​.param = param        ​

​}​

​}​

这样编译器会报如下错误:

'required' initializer 'init(coder:)' must be provided by subclass of 'UITabBarController'

Super.init isn't called before returning from initializer

原因分析:

1,在 Swift 中, 类的初始化器有两种, 分别是Designated Initializer(指定初始化器)和Convenience Initializer(便利初始化器)

2,如果子类没有定义任何的指定初始化器, 那么会默认继承所有来自父类的指定初始化器。

3,如果子类提供了所有父类指定初始化器的实现, 那么自动继承父类的便利初始化器

4,如果子类只实现部分父类初始化器,那么父类其他的指定初始化器和便利初始化器都不会继承。

5,子类的指定初始化器必须要调用父类合适的指定初始化器。

分析这两个错误:

1,第一个错误因为init(coder aDecoder: NSCoder) 方法是来自父类的指定构造器, 因为这个构造器是 required,

必须要实现. 但是因为我们已经重载了 init(), 定义了一个指定构造器, 所以这个方法不会被继承, 要手动覆写。

2,第二个错是因为指定构造器必须调用它最近父类的指定构造器。 

最终正确的写法:

13

14

15

16

17

18

19

20

21

​class​

​MainTabViewController​

​:​

​UITabBarController​

​{​

​var​

​param:​

​String​

​?​

​init​

​(param: ​

​String​

​) {​

​self​

​.param = param        ​

​super​

​.​

​init​

​(nibName: ​

​nil​

​, bundle: ​

​nil​

​)​

​}​

​required​

​init​

​?(coder aDecoder: ​

​NSCoder​

​) {​

​fatalError(​

​"init(coder:) has not been implemented"​

​)​

​}​

​override​

​func​

​viewDidLoad()​

​{      ​

​}​

​}​

​self​

​.presentViewController(​

​MainTabViewController​

​(param: ​

​"这个是传递的参数"​

​), animated:​

​true​

​, ​

​completion:​

​nil​

​)​