第十七章 Swift 类
2019-06-06 本文已影响0人
我有小尾巴快看
Swift 类可以没有基类,自己作为基类则没有super。
class Model {
}
class Model1: NSObject {
override init() {
super.init()
}
}
class Model2: Model {
}
类和结构体相比,拥有继承、动态等能力,并且是引用计数管理内存。
1.创建一个类
创建基类相对继承父类代码要简洁,这里仅用继承父类举例。
class ViewController: UIViewController {
let fps: Int
init(fps: Int) {
self.fps = fps
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
上例中创了一个继承UIViewController
的类ViewController
,他有一个fps
属性,在使用super前必须将自身全部属性初始化完毕,然后才能调用父类的designed init
。
2. 重写父类方法
重写方法必须先加上override
关键字,可以通过super
调用父类实现。
override func viewDidLoad() {
super.viewDidLoad()
}
如果父类方法添加了关键字required
,则子类必须实现该方法。
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
注意:子类重写的函数和属性,其权限不能小于父类权限。
// error: Overriding property must be as accessible as its enclosing type
override private var supportedInterfaceOrientations: UIInterfaceOrientationMask { return .portrait }
3. 重写父类扩展的方法
扩展的方法必须加上@objc
才能被子类重写,重写时也需要加上@objc
extension UIViewController {
func log() {
print("UIViewController")
}
}
extension ViewController {
// error: Overriding non-@objc declarations from extensions is not supported
override func log() {
print("ViewController")
}
}
extension UIViewController {
@objc func log() {
print("UIViewController")
}
}
extension ViewController {
@objc override func log() {
print("ViewController")
}
}
4. Runtime
Swift类需要使用Runtime则必须继承NSObject
以及添加@objc
标记,包括要用到的属性。
@objcclass User: NSObject {
@objc let name: String
@objc let age: UInt
init(name: String,
age: UInt) {
self.name = name
self.age = age
}
func keyValues() -> [String: Any] {
var res = [String: Any]()
var count: UInt32 = 0
let properties = class_copyPropertyList(self.classForCoder, &count)
for i in 0..<count {
guard let property = properties?[Int(i)] else { continue }
let name = String(cString: property_getName(property))
let value = self.value(forKey: name)
res[name] = value
}
return res
}
}
如果觉得给每个属性添加@objc
比较麻烦,可以添加@objcMembers
,这样所有属性都可以被runtime
捕捉到。
@objcMembers class User: NSObject {
let name: String
let age: UInt
init(name: String,
age: UInt) {
self.name = name
self.age = age
}
func keyValues() -> [String: Any] {
var res = [String: Any]()
var count: UInt32 = 0
let properties = class_copyPropertyList(self.classForCoder, &count)
for i in 0..<count {
guard let property = properties?[Int(i)] else { continue }
let name = String(cString: property_getName(property))
let value = self.value(forKey: name)
res[name] = value
}
return res
}
}
5. 与OC交互
Swift类导入OC则必须继承NSObject
以及添加@objc
标记,同时可以利用@objc
提供OC专用别用,而OC导入Swift则简单的多。
- 可以使用
@objc
重命名
@objc(PKUser) class User: NSObject {
}
@objc(testInOC) func test() {
}
@objc(testForOCWithA:orB:andC:) func test(a:Any, b:Any, c:Any) {
}
- 不想暴露给OC可以添加
@nonobjc
,但是现在默认不添加@objc
了,故@nonobjc
仅在@objcMembers
下隐藏某些内容有用(之前的版本默认给函数和属性添加@objc
,有@objc
才会暴露给OC)。
@nonobjc func swiftOnly() {
}
6. 引用循环
可以使用weak
避免引用循环
weak var delegate: UITableViewDelegate?
在闭包中可以使用unowned
和weak
避免引用循环。(详解在闭包章节)
let block1 = { [unowned self] in
print(self.view)
}
let block2 = { [weak self] in
print(self?.view)
}
7. 与OC的不同
- Swift的资源释放在
deinit
中完成,dealloc
不再被提供。 - Swift没有
load
函数