站在汇编角度深入了解 Swift(十一)
2020/4/6 23:31:48
本文主要是介绍站在汇编角度深入了解 Swift(十一),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
可选链(Optional Channing)
- 如果可选项为 nil,调用方法、下标、属性失败,结果为 nil
- 如果可选项不为 nil,调用方法、下标、属性成功,结果会被包装成可选项
- 如果结果本来就是可选项,不会进行再次包装
协议
- 协议中定义属性时必须用 var 关键字
- 因为你有可能是用计算属性实现的,那么这个值就不确定了,所以不能使用 let 关键字
- 实现协议时的属性权限要不小于协议中定义的属性权限
- 协议定义 { get set },用 var 存储属性或 get、set计算属性去实现
- 协议定义 get,用任何属性都可以实现
- 为了保证通用,协议中必须用 static 定义类型方法、类型属性,类型下标
mutating
- 只有将协议中的实例方法标记为 mutating
- 才允许结构体、枚举的具体实现修改自身内存
- 类在实现方法时不用加 mutating,枚举、结构体才需要加 mutating
init
- 协议中还可以定义初始化器 init
- 非 final 类实现时必须加上 required
- 如果协议实现的初始化器,刚好是重写了父类的指定初始化器
- 那么这个初始化器必须同时加 required、override
- init、init?、init!
- 协议中定义的 init?、init!,可以用 init、init?、init! 去实现
- 协议中定义的 init,可以用 init、init! 去实现
protocol Drawable { func draw() var x: Int { get set } var y: Int { get } subscript(index: Int) -> Int { get } } class Person: Drawable { var x: Int = 0 let y: Int = 10 func draw() { print("Person draw") } subscript(index: Int) -> Int { return index } } 复制代码
协议组合
- 可以包含很多个协议,可以包含一个类类型(最多一个)
protocol P1 { } protocol P2 { } class Person { } func fn0(obj: P1 & P2 & Person) { } 复制代码
CaseIterable
- 让枚举遵守 CaseIterable 就可以遍历枚举
enum Season { case spring, summer, autumn, winter } extension Season: CaseIterable { } func test34() { let seasons = Season.allCases print(seasons) } 复制代码
CustomStringConvertible
- 遵守 CustomStringConvertible 协议,可以自定义实例的打印字符串
- 和 OC 中的 description一样
Any、AnyObject
- Swift 提供了2种特殊的类型
- Any:可以代表任意类型(枚举、结构体、类,也包含函数类型)
- AnyObject:可以代表任意类类型(在协议后面写上: AnyObject 代表只有类能遵守这个协议),在后面加 class 关键字也有这个作用
is、as?、as!、as
- is 用来判断是否为某种类型,as用来强制类型转换
- as? 表示可能转换失败, as! 表示对 as? 的结果进行解包
(stu as? Student)?.study() // 转化有可能会失败,失败的时候方法不调用 (stu as? Student)!.study() // 转化有可能会失败,但也强制解包,所以有可能发生闪退 (stu as! Student).study() // 和上面的完全等价,可以看成是上面这种写的简写 复制代码
as 在编译器层面就能确保你转换是一定能够成功的了 var d = 10 as Double 复制代码
X.self、X.Type、AnyClass
- X.self 是一个元类型(metadata)指针,metadata 存放着类型相关信息。
- 也就是堆内存的首8个字节
- X.self 属于 X.Type 类型
- public typealias AnyClass = AnyObject.Type
class Person { } class Student: Person { } let person = Person() var perType: Person.Type = Person.self let stuType: Student.Type = Student.self perType = Student.self var anyType: AnyObject.Type = Person.self anyType = Student.self // public typealias AnyClass = AnyObject.Type var anyType2: AnyClass = Person.self anyType2 = Student.self ---------------------汇编分析--------------------- register read rax rax = 0x0000000100014e48 type metadata for Person #1 in swiftstudy.test36() -> () (lldb) register read rax rax = 0x0000000102900000 (lldb) x/5wg 0x0000000102900000 0x102900000: 0x0000000100014e48 0x0000000000000002 0x102900010: 0x0000000000000000 0x0000000000000000 0x102900020: 0x2f6d657473790017 复制代码
从上面的汇编也验证了,其实X.self就是一个元类型(metadata)指针
元类型的使用
class Person { var age: Int = 0 } class Student: Person { var no: Int = 0 } print(class_getInstanceSize(Person.self)) print(class_getSuperclass(Student.self)!) print(class_getSuperclass(Person.self)!) ---------------------汇编分析--------------------- 24 Person _TtCs12_SwiftObject 复制代码
可以看出来, Swift 还有个隐藏的基类:Swift.__SwiftObject,其实他和 oc 一样,前8个字节存的也是 isa 指针(就是用于查找他的类信息的),其实也可以理解,打印所有的纯 swift 对象,可以发现一个规律,就是前8个字节存储 isa,后面跟着8个字节存储引用计数,把他们抽成一个父类其实更合理。
Self
- Self 一般用作返回值类型,限定返回值方法调用者必须是同一类型(也可以作为参数类型)
- 如果 Self 用在类中,要求返回时调用的初始化是 required 的
- 一般如果我想链式调用的话,会这样写
class Person { required init() { } func test() -> Self { Self.self.init() } func test1() -> Self { Self.self.init() } } class Student: Person { } let p = Person().test().test1() 复制代码
思考
-
type(of: p) == Person.self? type(of: p) 和 sizeof 这种是一样的,本质不是调用函数,只是将 p 的前8个字节取出来,所以 type(of: p)和 Person.self 是相等的
-
Person 和 Person.self 的异同
class Person { static var age = 0 static func run() {} } Person.age = 10 Person.self.age = 20 func test(_ cls: AnyClass) { } test(Person.self) 复制代码
也就是说当你明确需要传 X.Type 的时候,这个时候X.self,不然用类名一般就够用了
这篇关于站在汇编角度深入了解 Swift(十一)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-10-05Swift语法学习--基于协议进行网络请求
- 2022-08-17Apple开发_Swift语言地标注释
- 2022-07-24Swift 初见
- 2022-05-22SwiftUI App 支持多语种 All In One
- 2022-05-10SwiftUI 组件参数简写 All In One
- 2022-04-14SwiftUI 学习笔记
- 2022-02-23Swift 文件夹和文件操作
- 2022-02-17Swift中使用KVO
- 2022-02-08Swift 汇编 String array
- 2022-01-30SwiftUI3.0页面反向传值