第十七章 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(PKUser) class User: NSObject {

}

@objc(testInOC) func test() {
 
}

@objc(testForOCWithA:orB:andC:) func test(a:Any, b:Any, c:Any) {

}

@nonobjc func swiftOnly() {
        
}

6. 引用循环

可以使用weak避免引用循环

weak var delegate: UITableViewDelegate?

在闭包中可以使用unownedweak避免引用循环。(详解在闭包章节)

let block1 = { [unowned self] in
    print(self.view)
}

let block2 = { [weak self] in
    print(self?.view)
}

7. 与OC的不同

上一篇 下一篇

猜你喜欢

热点阅读