1.命名空间
- 在同一个项目中,所有的类都是共享的,可以直接访问,不用import
- 不同的项目中有相同的类,是可以共存的
2.构造函数
- 是一种特俗的函数
- 主要用来在创建对象时,初始化对象
- 给对象的成员变量设置初始值
- Swift支持函数重载,所有构造函数都是init
- 作用: 分配空间,设置初始值
** 注意
- Object-c的初始化,是从类继承关系链,从父类开始逐级向子类初始化
Swift的初始化,是先从子类开始,逐级向父类初始化
非optonal属性,都必须在构造函数中设置初始值,从而保证对象再被实例化的时候,属性都被正确地初始化
- 在调用父类构造函数之前,必须保证本类的属性已经完成初始化
Swift中的构造函数不用写func关键字
1.构造函数的目的是: 给自己的属性分配空间并且设置初始值
2.调用父类构造函数之前,需要先给本类的属性设置初始值
3.调用父类的构造函数,给父类的属性分配空间并设置初始值
4.如果重载了构造函数,并且没有实现父类的init方法,系统不再提供init函数(默认会提供的),
5.默认的构造函数不能给本类的属性分配空间
3.重载与重写
重载: overload
- 函数名相同
- 参数类型和个数不同
- 如果重载了构造函数,并没有实现父类的init方法,系统不再提供init()构造函数
- 默认的init()构造函数,不能给本类的属性分配空间
重写: override
- 父类中已存在此方法
- 子类重新实现父类的方法
class ZYImage: NSObject {
var name:String
//重写
override init() {
name = "zhouyu"
super.init()
}
//重载
init(name: String) {
self.name = name
super.init()
}
}
override func viewDidLoad() {
super.viewDidLoad()
let image = ZYImage()
print(image.name)
let image2 = ZYImage(name: "wangwu")
print(image2.name)
}
4. KVC构造函数
要搞清一个问题
- iOS开发中,很多类的属性都是需要用到的时候才创建的,所以是可选的
- 定义模型属性时,如果是对象,通常是可选的: 需要的时候才创建,延迟加载,避免写构造函数 例如: var name: String?
KVC 是 OC 特有的,KVC 本质上是在运行时,动态向对象发送 setValue:ForKey: 方法,为对象的属性设置数值.
- 因此,在使用 KVC 方法之前,需要确保对象已经被正确实例化.
- 必选属性必须在调用父类构造函数之前完成初始化分配工作
- 基本数据类型在Swift ,与KVC不兼容
如果基本数据类型为nil,KVC在调用 setValue(value: AnyObject?, forKey key: String) 找不到这个属性, 使用KVC时给基本数据类型设置初始值
import UIKit
class Person: NSObject {
/// 姓名
var name: String?
/// 年龄
var age: Int = 0
/// `重写`构造函数
///
/// - parameter dict: 字典
/// - returns: Person 对象
init(dict: [String: Any]) {
super.init()
setValuesForKeys(dict)
}
override func setValue(_ value: Any?, forKey key: String) {
print("\(key) \(String(describing: value))")
}
override func setValue(_ value: Any?, forUndefinedKey key: String) {
print("\(key) \(String(describing: value))")
}
}
let person = Person(dict: ["name": "zhouyu" ,"age": 28])
5.Swift 4.0运行时获取类的属性列表
import UIKit
//@objcMembers Swift 4.0后,必须写,运行时才能获取属性
@objcMembers class Person: NSObject {
/// 姓名
var name: String?
/// 年龄
var age: Int = 0
/// 性别
var sex: String?
class func getClassPropertyList() -> [String] {
var propertyList:[String] = []
var count: UInt32 = 0
//UnsafeMutablePointer<objc_property_t>? 数组
let list = class_copyPropertyList(self, &count)
for i in 0..<Int(count) {
//objc_property_t
guard let property = list?[i] else { continue }
//UnsafePointer<Int8> Int8-->Byte-->Char-->C语言的字符串
let propertyCharName = property_getName(property)
//C语言的字符串转Swift的String
guard let propertyName = String(utf8String: propertyCharName) else { continue }
propertyList.append(propertyName)
}
free(list)
return propertyList
}
}
print(Person.getClassPropertyList())
//结果
["name", "age", "sex"]
1.基本数据类型,在OC中没有可选值这一说,如果定义成可选项,KVC获取不到,会崩溃
2.private修饰的属性,运行时同样获取不到此属性,也会是KVC崩溃
3.在Swift 4中继承 NSObject 的 swift class 不再默认全部 bridge 到 OC,如果想使用运行时获取类的细节,需要在class前面加上@objcMembers关键字。
6.便利构造函数
- convenience关键字修饰init(), 可以返回nil
- 只有便利构造函数中可以调用self.init()
- 便利构造函数不能被重写和super
- 用于条件检测和简化对象创建
- 常用与UIKit中,使用类工厂方法快速创建类似的控件
convenience init?(name: String, age: Int, sex: String) {
//书写判断条件
if age <= 0 {
return nil
}
//MARK: 调用self.init
self.init()
//给属性赋值
self.name = name
self.age = age
self.sex = sex
}