您的位置:首页 > 移动开发 > Swift

init?(coder aDecoder: NSCoder)

2016-05-04 10:50 381 查看
Mast call a designated initializer of the superclass

‘required’ initializer ‘init(coder:)’ must be provided by subclass of

如果你要用
Swift
创建一个实现了
NSCoding
协议的类(
UIView,UIViewController
)的子类的时候,你就会发现一种很尴尬的情况,
required init?(coder aDecoder: NSCoder)
, 还是必须实现的,然而你可能并不知道这是什么鬼,也不知道有什么卵用,你可能只是简单的知道他是
NSCoding
的协议方法而已.

Swift
中,如果你要重写父类的构造器,并且父类实现了
NSCoding
,那么在子类中你也必须实现这个构造器

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


所以你觉得万事大吉了,对不起,你错了。
Swift
在类初始化时,出于对安全性的考虑,对类的所有内部属性必须全部被初始化(通俗一点就是分配一个默认值),否则编译器报错,next eg.

class ViewController: UIViewController {
var name: String
var age : Int
init() {
name = "Paul"
age = 24
super.init(nibName: nil, bundle:nil)
}
required init(coder: NSCoder) {
super.init(coder: coder)
}
}


有些人说话了,谁说了一定要初始化,比如
var age : Int?
就不需要在
super.init()
之前必须初始化,
?
是可选型符号,这种写法规定你的
age
属性是个可选型,什么是可选型,可选型是指,在你没有赋值的情况下默认赋值为
nil
,所以即使
age
定义的时候没有初始化,但是它已经被初始化了(nil 表示空值,和OC中的空对象区别,例如 Swift 中是不能通过 age=nil 来释放一个对象的),

但是,如果你想要实现一个自定义的构造器,怎么做,我猜可能是这样

class ViewController: UIViewController {
let name: String
init() {
name = "Paul"
super.init(nibName: nil, bundle:nil)
}
init(name aName : String) {
name = "Paul"
super.init(nibName: nil, bundle:nil)
}
required init(coder: NSCoder) {
name = "Paul"   \\ 索性都写上,
super.init(coder: coder)
}
}


如果我有10个,100个属性呢?耗时间,那干脆想oc一样,写一个赋值的方法

class ViewController: UIViewController {
let name: String
init() {
setup()
super.init(nibName: nil, bundle:nil)
}
init(name aName : String) {
setup()
super.init(nibName: nil, bundle:nil)
}
required init(coder: NSCoder) {
setup()
super.init(coder: coder)
}
func setup() {
name = "Paul"
age = 25
}
}


这样一来有一百个也无妨,想法很不错,有见地,但是很可惜,编译未通过,(举个例子,对象好比蛋里面的鸡,属性是肌肉,方法是鸡翅、鸡爪等),在
super.init
之前(蛋孵化之前),方法也同样没有被初始化(鸡都没有孵出来,你就想烤鸡翅了?)

废话说了这么多,到底怎么解决呢,别着急,

class ViewController: UIViewController {
let name: String
// 自定义的构造器
init(_ coder: NSCoder? = nil) {
name = "Paul"
if let coder = coder {
super.init(coder: coder)!
} else {
super.init(nibName: nil, bundle:nil)
}
}
required convenience init(coder: NSCoder) {
self.init(coder)
}
// 下面这句可省去
override convenience init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
self.init(nil)
}
}


像这样,我们在我们自定义的构造器
init(_ coder: NSCoder? = nil)
中添加了一个可选型的
NSCoding
的参数,默认是nil,所以我们像之前那样不用任何参数调用
init(nil)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息