本文翻译于The Official raywenderlich.com Swift Style Guide。目前更新到 Swfit4.2。
前言:作为一名开发人员,须知好的代码规范,不仅能够提升代码的可读性、提升开发效率同时也会对让团队间的开发沟通效果得到加强。针对Swift语言raywenderlich.com给出来一份较为完善的开发指南。本文就是基于原文翻译而成。英文水平较好这可点击上方链接,查看原文。
开发警告⚠️规范
开发者应该努力做到代码没有警告的通过编译,此规则会由许多的代码编写风格来决定,例如使用#selector
类型来代替字符串字母量、尽量避免使用标记了DEPRECATED
的API等。
命名规范
描述性和一致性的命名会使代码更易于阅读和理解。苹果官方的API设计指南中也描述了Swift的命名约定,一些关键点包括:
- 命名应当清晰。
- 命名清晰度的重要性大于简洁性,尽可能的表达清晰而不用害怕命名过长。
- 使用驼峰法命名。
- 命名针对类型和协议使用大写字母开头,其它都已小写字母开头。
- 尽量包含所需要的单词,同时省略不必要的单词。
- 命名的名称应当基于当前语义,而不是类型。
- 对信息缺失的命名可以适当补充。
- 命名尽量使用流畅的语法
- 工厂方法以
make
开头 - 命名方法考虑以下因素
- 不可变(non-mutating)的动词方法后接 -ed、-ing。
- 不可变(non-mutating)的名词方法遵守
formX
- boolean 类型的方法阅读应当类似断言。只有是、否两种含义。
- 描述某些东西的协议应该被理解为名词(例如Collection)。
- 描述一个协议能力应该使用后缀命名able,ible或ing (例如Equatable,ProgressReporting)。
- 使用通俗易懂的术语,无论是新手还是专家都能轻松接受。
- 一般来说避免使用缩写。
- 使用既定成俗的命名。
- 首选方法和属性来代替函数。
- 通常缩略语和首字母缩略词应根据案例惯例统一大写或小写。
- 为具有相同含义的方法指定相同的基名。
- 避免方法的返回值过多。
- 将方法名称命名部分放在第一个参数名中。
- 选择好的方法参数名称,见文知意,起到好的说明效果。
- 对闭包和元组类型参数说明
- 利用好默认参数。
类前缀
Swift类型由包含它们的模块自动命名,并且不应添加类前缀,例如RW。如果来自不同模块的两个名称发生冲突,则可以通过在类型名称前加上模块名称来消除歧义。但是,只有在存在混淆的时才指定模块名称,这在平时开发中应该很少出现。
import SomeModule
let myClass = MyModule.UsefulClass()
Delegates
创建自定义委托方法时,未命名的第一个参数应该是代理源。
推荐:
func namePickerView(_ namePickerView:NamePickerView,didSelectName name:String)
func namePickerViewShouldReload(_ namePickerView:NamePickerView)- > Bool
不推荐:
func didSelectName(namePicker: NamePickerViewController, name: String)
func namePickerShouldReload() -> Bool
类型推导
使用Swift的类型推导功能,减少代码量,提升代码简洁性
推荐:
let selector = #selector(viewDidLoad)
view.backgroundColor = .red
let toView = context.view(forKey: .to)
let view = UIView(frame: .zero)
不推荐:
let selector = #selector(ViewController.viewDidLoad)
view.backgroundColor = UIColor.red
let toView = context.view(forKey: UITransitionContextViewKey.to)
let view = UIView(frame: CGRect.zero)
泛型
泛型类型的参数应该具有描述性的,按驼峰命名。当一个泛型类名没有一个有意义的名称,可以使用传统的单大写字母代替,例如T,U或V。
推荐:
struct Stack<Element> { ... }
func write<Target: OutputStream>(to target: inout Target)
func swap<T>(_ a: inout T, _ b: inout T)
不推荐:
struct Stack<Element> { ... }
func write<Target: OutputStream>(to target: inout Target)
func swap<T>(_ a: inout T, _ b: inout T)
语法
使用美式的语法,美式语法会更加匹配苹果的API。
推荐:
let color = "red"
不推荐:
let colour = "red"
代码结构
使用extensions来组织你的代码结构,每个extension中应该是一整块的相关代码。每个extensions之前都应添加// MARK: -
注释。
协议一致性
遵守协议时,针对每个协议下的方法添加单独的扩展,使得协议方法组合在一起。
推荐:
class MyViewController: UIViewController {
// class stuff here
}
// MARK: - UITableViewDataSource
extension MyViewController: UITableViewDataSource {
// table view data source methods
}
// MARK: - UIScrollViewDelegate
extension MyViewController: UIScrollViewDelegate {
// scroll view delegate methods
}
不推荐:
class MyViewController: UIViewController, UITableViewDataSource, UIScrollViewDelegate {
// all methods
}
在UIKit中的Viewcontroller
中可以使用Extension来分离自定义访问器和IBAction。
未使用的代码
应当删除未使用的代码包括Xcode的模板代码和默认的注释、去除没有意义的代码。
推荐:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Database.contacts.cou