第二周:Swift代码书写规范

起点

注意:代码中存在换行和缩进不规范的问题

命名规范

通用
  • 禁止使用拼音命名
  • 多个相似命名中禁止出现类似lab1、lab2、lab3的情况
  • 尽量避免“简称”和“缩略词”,通用缩略词应该整体大写或整体小写
  • 使用驼峰式命名方式,命名使用小写字母开头,常量最好使用k开头

推荐:

1
2
3
4
5
private let maximumWidgetCount = 100
class WidgetContainer {
var widgetButton: UIButton
let widgetHeightPercentage = 0.85
}
1
2
let urlString: URLString
let userID: UserID

不推荐:

1
2
3
4
5
let MAX_WIDGET_COUNT = 100
class app_widgetContainer {
var wBut: UIButton
let wHeightPct = 0.85
}
1
2
let uRLString: UrlString
let userId: UserId
  • 命名是做到见名知意,尽量少使用全局变量
  • 一个变量有且只有一个功能,尽量不要把一个变量作为多种用途
  • 每个枚举值用小写字母开始
1
2
3
4
5
6
enum Shape {
case rectangle
case square
case rightTriangle
case equilateralTriangle
}
文件
  • 工程文件命名禁止使用中文,首字母大写
  • 资源文件命名(图片、文件等),首字母小写,且统一家里在资源文件中
  • 创建新文件夹时必须保证工程目录与finder中的文件目录统一,且在工程中一般使用group

格式规范

函数
  • 函数尽量控制入参数量,最好有必要的入参,尽量少使用无入参方法名
  • 单个方法体不应超过100行,超过100行需重构
  • 方法与方法之间需空行,方法内的局部变量和方法的第一条语句之间需空行
  • 当调用的函数有多个参数时,每一个参数另起一行,并比函数名多一个缩进
注释
  • 文档注释、块注释或单行注释之前,引用包注释可以不用空行
  • 变量注释尽量写在变量的后面,对齐
  • 实现文件中.函数的注释用#MARK - description -
  • 代码难以理解处添加注释
  • 对于负责的类,在描述类的使用方法时可以添加一些合适的例子,请注意Swift注释是支持 MarkDown 语法的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
  ##功能列表
 这个类提供下一下很赞的功能,如下:
 - 功能 1
 - 功能 2
 - 功能 3
 ## 例子
 这是一个代码块使用四个空格作为缩进的例子。
     let myAwesomeThing = MyAwesomeClass()
     myAwesomeThing.makeMoney()
 ## 警告
 使用的时候总注意以下几点
 1. 第一点
 2. 第二点
 3. 第三点
 */
class MyAwesomeClass {
    /* ... */
}
代码的排列
  • 类遵循代理,写在MyClass{}的下方,使用Extension, 例如:extension MyClass: UITableViewDelegate{}

推荐:

1
2
3
4
5
6
7
8
9
10
11
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
}

不推荐:

1
2
3
class MyViewcontroller: UIViewController, UITableViewDataSource, UIScrollViewDelegate {
// all methods
}
  • 控制器之间的跳转方法写在MyClass的作用域的最后
  • 构造方法和生命周期写在成员变量的下方
  • UIKit view controllers,将lifecycle,custom accessors, and IBAction等方法单独放在一个 class extension
  • 无用的code ,包括 Xcode 注释都应该被移除。空方法应该被移除

推荐:

1
2
3
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Database.contacts.count
}

不推荐:

1
2
3
4
5
6
7
8
9
10
11
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return Database.contacts.count
}
  • 可以用命令Ctrl+I重新排列代码

其他

运算符与变量间的空格
  • 一元运算符与变量之间无空格,二元运算符与变量之间必须有空格
1
2
3
4
5
!bValue
~iValue
++iCount
*strSource
&fSum
1
2
3
fWidth = 5 + 5
fLength = fWidth * 2
fHeight = fWidth + fLength
if语句
  • 必须列出所有分支(穷举所有情况),每一个分支必须给出明确的结果
  • 连续分支间使用if else连接

推荐:

1
2
3
4
5
if count < 3 {
copyString = "Hello"
}else{
copyString = ""
}

不推荐:

1
2
3
if count < 3 {
copyString = "Hello"
}
1
2
3
4
5
6
7
var weight: Int = 30
if weight >= 10 {
//TODO
}
if weight < 10 {
//TODO
}
  • 不要使用过多的分支,善于使用return提前返回错误

推荐:

1
2
3
4
5
6
func customMethod(){
if x < 0 {
return
}
//TODO
}
1
2
3
4
guard n.isNumber else {
return
}
// Use n here

不推荐:

1
2
3
4
5
func customMethod(){
if x >= 0 {
//TODO
}
}
  • 多个条件判断时,不要多个if嵌套,用 guard

推荐:

1
2
3
4
5
6
func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {
guard let context = context else { throw FFTError.noContext }
guard let inputData = inputData else { throw FFTError.noInputData }
// use context and input to compute the frequencies
return frequencies
}

不推荐:

1
2
3
4
5
6
7
8
9
10
11
12
func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {
if let context = context {
if let inputData = inputData {
// use context and input to compute the frequencies
return frequencies
} else {
throw FFTError.noInputData
}
} else {
throw FFTError.noContext
}
}
  • 如果需要把访问修饰符放到第一个位置
1
2
3
4
// 推荐
private static let kMyPrivateNumber: Int
// 不推荐
static private let kMyPrivateNumber: Int
  • 声明单例属性可以通过下面方式进行
1
2
3
4
class PirateManager {
    static let sharedInstance = PirateManager()
    /* ... */
}
  • 避免使用self去调用属性或方法,仅在初始化方法的参数名和属性名相同时用self
1
2
3
4
5
6
7
8
9
10
class BoardLocation {
let row: Int, column: Int
init(row: Int, column: Int) {
self.row = row
self.column = column
let closure = {
print(self.row)
}
}
}
  • 如果一个计算属性的返回值很简单,可以省去 get{}。有 set{} 就一定要有 get{}

推荐:

1
2
3
4
5
6
7
8
9
var diameter: Double {
return radius * 2
}
var myGreatProperty: Int {
return 4
}
subscript(index: Int) -> T {
return objects[index]
}

不推荐:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var diameter: Double {
get {
return radius * 2
}
}
var myGreatProperty: Int {
get {
return 4
}
}
subscript(index: Int) -> T {
get {
return objects[index]
}
}

后记:

  • 初版比较粗糙,文档会在之后更多的实践中增加和修改
  • 如有错误或不当的地方欢迎留言指正,在此感谢!

参考文档:

https://github.com/github/swift-style-guide
http://www.jianshu.com/p/288ea00dcfcf