Swift 于 2015 年正式开源。
一、目录简介
Github:https://github.com/apple/swift
几个可能会经常看的目录:
- docs:一些文档
- stdlib:Swift 源码
- lib:C++源码
- include:C++头文件
标准库源码位置:
https://github.com/apple/swift/tree/main/stdlib/public/core
二、Metadata 分析
文档:https://github.com/apple/swift/blob/master/docs/ABI/TypeMetadata.rst
2.1. 结构布局
类的前 8 个字节存储的就是类相关的信息,指向Metadata
。那么Metadata
存储的是什么呢(官方文档也没细说,只能从 Swift 源码看下相关描述)?
-
Metadata
是区分类型的,不同类型的Metadata
是不同的(比如protocol、enum、class、struct、NSObject
等等是不同的Metadata
)。 -
Metadata
存储哪些内容和 ABI 有关,在 Swift5.0 的时候 ABI 已经稳定下来了(官方对应版本描述为 Stable)。而 ABI 稳定意味着Metadata
结构已经稳定(比如 Swift2.0 的class
在Metadata
结构中的第 32 字节位置开始,可能在 Swift4.0 的时候变为第 48 字节位置开始存储,其他类型的存储位置也可能已经发生变化)。
虚表的
0x50
偏移量就是偏移其类型的Metadata
所占字节。
2.2. 作用
Metadata
的作用是什么呢?
在 OC 中如果要想知道一个类有哪些属性,可以通过runtime
的一些方法获取。但在纯 Swift 中,要想知道对应类型有哪些存储属性,只能通过Metadata
获取。
经典应用场景:字典转模型(JSON -> Model)。
但是由于每种类型的Metadata
结构布局不一样,所以需要对很多类型做布局解析。
三、反射
反射是编程语言中一项强大的能力,比如 Java 语言的反射机制。
- 对于任意一个类型,都能够动态获取这个类的所有属性和方法信息
- 对于任意个实例,都能够动态调用它的任意方法和属性
Swift 的反射机制目前还比较弱,通过Mirror
类型来提供简单的反射功能(只能获取到类型的属性名称,但是属性类型或泛型是获取不到的)。
示例代码:
struct Person {
var name: String?
var age: Int?
}
let mirror = Mirror(reflecting: Person(name: "daben", age: 20))
print(mirror.displayStyle as Any) // 输出:Optional(Swift.Mirror.DisplayStyle.struct)
print(mirror.subjectType) // 输出:Person
print(mirror.superclassMirror as Any) // 输出:Person
for case let (label?, value) in mirror.children {
print(label, value)
}
/*
输出:
name Optional("daben")
age Optional(20)
*/
四、常用第三方库
4.1. 网络请求
Github:https://github.com/Alamofire/Alamofire
4.2. 图片缓存
Github:https://github.com/onevcat/Kingfisher
Kingfisher 默认不支持 WebP 格式的图片,需要额外安装 KingfisherWebP
pod 导入:
pod 'KingfisherWebP'
使用方法:
imageView.setImage(with: URL(string: user.avatar),
options: [.processor(WebPProcessor.default),
.cacheSerializer(WebPSerializer.default)])
4.3. JSON 访问
Github:https://github.com/SwiftyJSON/SwiftyJSON
注意:该库仅仅是为了方便访问 JSON,而不是 JSON 转 Model
4.4. 字典转模型(JSON-Model)
Github:https://github.com/kakaopensource/KakaJSON
五、前缀
为防止和系统 API 或第三方库命名冲突,OC 中经常在类名、方法、属性前面加前缀(如 DBViewController)。
但是在 Swift 中不需要加前缀,也不建议加前缀。因为当函数名和第三方库函数冲突的时候可以使用库名区分。
示例代码:
// 自定义函数
func request(...)
// 第三方库函数
AF.request(...)
六、全局引入
以前 OC 常用pch
作为预编译头文件导入第三方库,在纯 Swift 中如果需要全局导入,可以借助 OC 的桥接头文件{TargetName}-Bridging-Header.h
。
示例代码:
#import <SwiftyJSON/SwiftyJSON-Swift.h>
#import <UIKit/UIKit.h>
一般情况下,库的导入格式是:库名-Swift.h
。当导入格式不正确时,可以进入framework
查看头文件名称。
至此,Swift所有章节已经更新完毕,更多系列文章,请关注 微信公众号【1024星球】(文章都会首发到公众号内)。