Swift 類可以沒有基類粗合,自己作為基類則沒有super萍嬉。
class Model {
}
class Model1: NSObject {
override init() {
super.init()
}
}
class Model2: Model {
}
類和結(jié)構(gòu)體相比,擁有繼承隙疚、動態(tài)等能力壤追,并且是引用計數(shù)管理內(nèi)存。
1.創(chuàng)建一個類
創(chuàng)建基類相對繼承父類代碼要簡潔供屉,這里僅用繼承父類舉例行冰。
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")
}
}
上例中創(chuàng)了一個繼承UIViewController
的類ViewController
,他有一個fps
屬性伶丐,在使用super前必須將自身全部屬性初始化完畢悼做,然后才能調(diào)用父類的designed init
。
2. 重寫父類方法
重寫方法必須先加上override
關(guān)鍵字哗魂,可以通過super
調(diào)用父類實現(xiàn)肛走。
override func viewDidLoad() {
super.viewDidLoad()
}
如果父類方法添加了關(guān)鍵字required
,則子類必須實現(xiàn)該方法录别。
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
注意:子類重寫的函數(shù)和屬性朽色,其權(quán)限不能小于父類權(quán)限故硅。
// 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
標(biāo)記,包括要用到的屬性纵搁。
@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類導(dǎo)入OC則必須繼承NSObject
以及添加@objc
標(biāo)記腾誉,同時可以利用@objc
提供OC專用別用徘层,而OC導(dǎo)入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
,但是現(xiàn)在默認不添加@objc
了利职,故@nonobjc
僅在@objcMembers
下隱藏某些內(nèi)容有用(之前的版本默認給函數(shù)和屬性添加@objc
趣效,有@objc
才會暴露給OC)。
@nonobjc func swiftOnly() {
}
6. 引用循環(huán)
可以使用weak
避免引用循環(huán)
weak var delegate: UITableViewDelegate?
在閉包中可以使用unowned
和weak
避免引用循環(huán)猪贪。(詳解在閉包章節(jié))
let block1 = { [unowned self] in
print(self.view)
}
let block2 = { [weak self] in
print(self?.view)
}
7. 與OC的不同
- Swift的資源釋放在
deinit
中完成跷敬,dealloc
不再被提供。 - Swift沒有
load
函數(shù)