t()
// a,b,c类型一致,没有命名信息不清楚每个变量的含义
系统库
KVO
/Notification
使用 block
API
block
API的优势:
KVO
可以支持 KeyPath
- 不需要主动移除监听,
observer
释放时自动移除监听
不推荐
class Object: NSObject {
init() {
super.init()
addObserver(self, forKeyPath: "value", options: .new, context: nil)
NotificationCenter.default.addObserver(self, selector: #selector(test), name: NSNotification.Name(rawValue: ""), object: nil)
}
override class func observeva lue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
}
@objc private func test() {
}
deinit {
removeObserver(self, forKeyPath: "value")
NotificationCenter.default.removeObserver(self)
}
}
推荐
class Object: NSObject {
private var observer: AnyObserver?
private var kvoObserver: NSKeyValueObservation?
init() {
super.init()
observer = NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: ""), object: nil, queue: nil) { (_) in
}
kvoObserver = foo.observe(.value, options: [.new]) { (foo, change) in
}
}
}
Protocol
使用protocol
代替继承
Swift
中针对protocol
提供了很多新特性,例如默认实现
,关联类型
,支持值类型。在代码设计时可以优先考虑使用protocol
来避免臃肿的父类同时更多使用值类型。
提示:一些无法用protocol
替代继承
的场景:1.需要继承NSObject子类。2.需要调用super
方法。3.实现抽象类
的能力。
Extension
使用extension
组织代码
使用extension
将私有方法
/父类方法
/协议方法
等不同功能代码进行分离更加清晰/易维护。
class MyViewController: UIViewController {
// class stuff here
}
// MARK: - Private
extension: MyViewController {
private func method() {}
}
// MARK: - UITableViewDataSource
extension MyViewController: UITableViewDataSource {
// table view data source methods
}
// MARK: - UIScrollViewDelegate
extension MyViewController: UIScrollViewDelegate {
// scroll view delegate methods
}
代码风格
良好的代码风格可以提高代码的可读性
,统一的代码风格可以降低团队内相互理解成本
。对于Swift
的代码格式化
建议使用自动格式化工具实现,将自动格式化添加到代码提交流程,通过定义Lint规则
统一团队内代码风格。考虑使用SwiftFormat
和SwiftLint
。
提示:SwiftFormat
主要关注代码样式的格式化,SwiftLint
可以使用autocorrect
自动修复部分不规范的代码。
常见的自动格式化修正
- 移除多余的
;
- 最多只保留一行换行
- 自动对齐
空格
- 限制每行的宽度
自动换行
性能优化
性能优化上主要关注提高运行时性能
和降低二进制体积
。需要考虑如何更好的使用Swift
特性,同时提供更多信息给编译器
进行优化。
使用Whole Module Optimization
当Xcode
开启WMO
优化时,编译器可以将整个程序编译为一个文件进行更多的优化。例如通过推断final
/函数内联
/泛型特化
更多使用静态派发,并且可以移除
部分未使用的代码。
使用源代码
打包
当我们使用组件化
时,为了提高编译速度
和打包效率
,通常单个组件独立编译生成静态库
,最后多个组件直接使用静态库
进行打包。这种场景下WMO
仅针对internal
以内作用域生效,对于public/open
缺少外部使用信息所以无法进行优化。所以对于大量使用Swift
的项目,使用全量代码打包
更有利于编译器做更多优化。
减少方法动态
派发
使用final
- class
/方法
/属性
申明为final
,编译器可以优化为静态派发
使用private
- 方法
/属性
申明为private
,编译器可以优化为静态派发
避免使用dynamic
- dynamic
会使方法通过ObjC消息转发
的方式派发
使用WMO
- 编译器可以自动分析推断出final
优化为静态派发
使用Slice
共享内存优化性能
在使用Array
/String
时,可以使用Slice
切片获取一部分数据。Slice
保存对原始Array
/String
的引用共享内存数据,不需要重新分配空间进行存储。
let midpoint = absences.count / 2
let firstHalf = absences[..
`提示:应避免一直持有Slice,Slice会延长原始Array/String的生命周期导致无法被释放造成内存泄漏。
protocol添加AnyObject protocol AnyProtocol {}
protocol ObjectProtocol: AnyObject {}
当protocol仅限制为class使用时,继承AnyObject协议可以使编译器不需要考虑值类型实现,提高运行时性能。
使用@inlinable进行方法内联优化 // 原始代码 let label = UILabel().then { $0.textAlignment = .center $0.textColor = UIColor.black $0.text = "Hello, World!" }
以then库为例,他使用闭包进行对象初始化以后的相关设置。但是 then 方法以及闭包也会带来额外的性能消耗。