构造函数
设置 Optional 属性
- 自定义
Person
对象
class Person: NSObject {
var name: String
var age: Int
}
- 以上代码会报:“存储性属性没有初始化值”
- 解决办法:将对象属性类型设置为
Optional
class Person: NSObject {
var name: String?
var age: Int?
}
- 测试类
let p = Person()
p.name = "张三"
p.age = 18
print("\(p.name) --- \(p.age)")
- 输出结果:Optional(“张三”) — Optional(18)
利用 init
函数为属性初始化
- 如果在
init
中给对象的属性设置初始值,则对象的属性可以不用可选项 - 因为:只有调用了 init 函数之后,才能确保对象可用
class Person: NSObject {
var name: String
var age: Int
override init() {
name = "张三"
age = 19
}
}
重载构造函数
- Swift 中支持函数重载,同样的函数名,不一样的参数类型
init(name: String, age: Int) {
self.name = name
self.age = age
}
注意事项
- 如果重载了构造函数,但是没有实现默认的构造函数,则系统不再提供默认的构造函数
KVC 字典转模型构造函数
init(dict: [String: AnyObject]) {
setValuesForKeysWithDictionary(dict)
}
- 以上代码会报错
- 原因:使用 KVC 为对象属性设置数值前,需要确保对象已经被初始化
- 添加
super.init()
同样会报错 - 原因:调用父类的初始化方法,不会初始化本类对象的属性
- 解决办法:将属性修改为可选项
- 修改后的代码
var name: String?
var age: Int?
init(dict: [String: AnyObject]) {
super.init()
setValuesForKeysWithDictionary(dict)
}
运行测试,仍然会报错
错误信息:this class is not key value coding-compliant for the key age.
* 原因:在 Swift 中,如果对象的基本数据类型属性是可选的,则在初始化时,不会为该属性分配空间
* 解决办法:给基本数据类型设置初始值
* 修改后的代码如下:
var name: String?
var age: Int = 0
init(dict: [String: AnyObject]) {
super.init()
setValuesForKeysWithDictionary(dict)
}
提示:在定义类时,基本数据类型属性一定要设置初始值,否则无法正常使用 KVC 设置数值
子类构造函数
- 自定义子类时,需要在构造函数中,首先为本类定义的属性设置初始值
- 然后再调用父类的构造函数,初始化父类中定义的属性
class Student: Person {
var no: String
override init() {
print("Student init")
no = "001"
super.init()
}
}
convenience 构造函数
- 默认情况下,所有的构造方法都是指定构造函数
Designated
convenience
关键字修饰的构造方法就是便捷构造函数- 便捷构造函数可以返回
nil
- 只有便捷构造函数中可以调用
self.init()
- 便捷构造函数不能被继承
convenience init?(age: Int) {
if age > 20 && age < 60 {
self.init()
self.age = age
return
}
return nil
}
构造函数小结
- 指定构造函数必须调用其直接父类的的指定构造函数(除非没有父类)
- 便捷构造函数必须调用同一类中定义的其他构造函数
- 便捷构造函数可以返回
nil
- 便捷构造函数不能被继承
析构函数 deinit
- 一个对象被释放之前,析构函数会立即被自动调用
- 类似与 OC 的
dealloc
- 一般在析构方法中进行资源的释放
- 不允许主动调用析构函数
- 如果是继承的对象,会先调用本类的析构函数,再顺序调用父类的析构函数,以确保所有属性全部被释放