随着项目越来越大,编译时长也会越来越长。那么编译的优化就必不可少了。
查看编译时长
在 xcode 的编译 log 可以查看时长,也可以查看总时长,每一个 文件的编译时长。
swift 类型检查耗时
对于 swift 来说,编译耗时的主要就是类型检查
在 xcode => build settings => Other Swift Flags
添加下面设置,可以看到 swift 的表达式和函数的 类型检查的时长。并给出警告。
-Xfrontend -warn-long-function-bodies=100 (100 means 100ms here, you should experiment with this value depending on your computer speed and project)
-Xfrontend -warn-long-expression-type-checking=100
后面的 100 单位是毫秒,超过这个值,就会给出警告。
查看总耗时
在终端执行:
defaults write com.apple.dt.Xcode ShowBuildOperationDuration -bool YES
重启 xcode,编译可以看到总耗时
项目设置优化
使用 New Xcode Build System
dSYM
可以设置在 debug
不生成 dSYM
,只在 release
生成。
模块化
可以把 pod 等第三方库先打包成 .a 文件,然后再放入项目里面,这样 pod 的第三方库就编译时间就会减少。但是这样一来 调试就不方便了,所以这是个取舍问题。
Object-C 的优化
oc 的优化,重点在于减少无效引用,对编译时长的优化提升非常明显。 通过 log 看哪些文件编译时间比较长的文件,进行优化。
快捷键⌘ + 8
优化pch文件
1、检查 pch 文件,删除用的不多的引用。
h 文件
.h
文件尽量少写引用。引用尽量写在 .m
文件里。可以在编译 log 中看有哪些文件编译时间比较长的,大部分都可以通过 优化引用来解决。
删除不用引用
项目时间长了之后,因为功能变化,有些类可能已经不用了,但是引用还在,这个一定要删掉。
经过优化,编译时长减少了2-3 分钟。
Swift 优化
优化选择
根据之前说法,把 swift 的文件合并成一个,可以大大减少编译时长。但是 xcode10 已经没用这个选项了。 xcode10 已经给出了优化的选择,我们主要选择正确的选项就可以,根据自己的需求,一般 debug 选择 增量编译,Adhoc 和 Release 可以选择模块编译
原理可以参考: medium.com/rocket-fuel…
代码优化
swift 设置优化完之后,主要就是代码的优化了。swift 耗时的主要就是类型检查,那么代码优化的重点就是 检查哪些表达式、函数 类型检查占用太长时间。
可以用工具 Swift BuildTimeAnalyzer tool 来查看每一个文件的编译时长。
在网上查了各种说法,下面是 swift 代码优化的重点,也确实有用。
- 闭包和 lazy
不推荐
private(set) lazy var chartViewColors: [UIColor] = [
self.chartColor,
UIColor(red: 86/255, green: 84/255, blue: 124/255, alpha: 1),
UIColor(red: 80/255, green: 88/255, blue: 92/255, alpha: 1),
UIColor(red: 126/255, green: 191/255, blue: 189/255, alpha: 1),
UIColor(red: 161/255, green: 77/255, blue: 63/255, alpha: 1),
UIColor(red: 235/255, green: 185/255, blue: 120/255, alpha: 1),
UIColor(red: 100/255, green: 126/255, blue: 159/255, alpha: 1),
UIColor(red: 160/255, green: 209/255, blue: 109/255, alpha: 1),
self.backgroundGradientView.upperColor
]
推荐:
// Cumulative build time: 56.3ms
private(set) lazy var chartViewColors: [UIColor] = self.createChartViewColors()
// Build time: 6.2ms
private func createChartViewColors() -> [UIColor] {
return [
chartColor,
UIColor(red: 86/255, green: 84/255, blue: 124/255, alpha: 1),
UIColor(red: 80/255, green: 88/255, blue: 92/255, alpha: 1),
UIColor(red: 126/255, green: 191/255, blue: 189/255, alpha: 1),
UIColor(red: 161/255, green: 77/255, blue: 63/255, alpha: 1),
UIColor(red: 235/255, green: 185/255, blue: 120/255, alpha: 1),
UIColor(red: 100/255, green: 126/255, blue: 159/255, alpha: 1),
UIColor(red: 160/255, green: 209/255, blue: 109/255, alpha: 1),
backgroundGradientView.upperColor
]
}
Array
,Dictionary
集合类型 需要指明类型,并且不要用 +
来合并两个集合
- 三元运算符
?:
// Before
return someValue > 3 ? someValue - 2 : someValue + 2
// After
if someValue > 3 {
return someValue - 2
} else {
return someValue + 2
}
- 二元运算符
??
return CGSize(width: size.width + (rightView?.bounds.width ?? 0) + (leftView?.bounds.width ?? 0) + 22, height: bounds.height)
// After
var padding: CGFloat = 22
if let rightView = rightView {
padding += rightView.bounds.width
}
if let leftView = leftView {
padding += leftView.bounds.width
}
return CGSize(width: size.width + padding, height: bounds.height)
?:
和 ??
都可以通过 条件绑定来解决。
- 一行表达式不要做太多事情
不要在一个表达式中既做判断,又做计算
if number == 60 * 60 {
// ...
}
// After
let number: Double = 60 * 60
if number == 3600 {
// ...
}
代码优化可以参这里