每行代码长度限制

Swift 每行代码长度应该小于 100 个字符,或者说阅读的时候不应该需要滚动屏幕,在正常的实现范围里可以完整看到代码。除了以下列出的情况,否则超过这个长度应该换行。 例外的情况:

括号

非空的 block 花括号默认使用 K&R style。比如:
while (x == y) {
    something()
    somethingelse()
}
除了一些 Swift 特别要求的情况:

分号

无论是终止或者隔开声明都不会使用分号。也就是说分号只可能出现在文本中。
✅
func printSum(_ a: Int, _ b: Int) {
  let sum = a + b
  print(sum)
}
❌
func printSum(_ a: Int, _ b: Int) {
  let sum = a + b;
  print(sum);
}

每行只声明一件事

每行最多只声明一件事,每行结尾用换行分隔。除非结尾跟的是一个总共只有一行声明的闭包
✅
guard let value = value else { return 0 }

defer { file.close() }

switch someEnum {
case .first: return 5
case .second: return 10
case .third: return 20
}

let squares = numbers.map { $0 * $0 }

var someProperty: Int {
  get { return otherObject.property }
  set { otherObject.property = newValue }
}

var someProperty: Int { return otherObject.somethingElse() }

required init?(coder aDecoder: NSCoder) { fatalError("no coder") }
如果闭包是提前返回一个值,写在一行里可读性就会好一些。如果是一个正常的操作,可以视情况是否写在一行里。因为未来也有可能里面再增加代码的操作。

代码换行

Style guide: 代码换行

代码中的空格

除了语言或者其他样式的要求,文字和注释之外,一个Unicode空格也只出现在以下地方:

条件关键字后面和跟着的括号

✅
if (x == 0 && y == 0) || z == 0 {
  // ...
}

❌
if(x == 0 && y == 0) || z == 0 {
  // ...
}

如果闭包中的代码在同一行,左花括号的前面、后面,右花括号的前面有空格

✅
let nonNegativeCubes = numbers.map { $0 * $0 * $0 }.filter { $0 >= 0 }

❌ 
let nonNegativeCubes = numbers.map { $0 * $0 * $0 } .filter { $0 >= 0 }

❌
let nonNegativeCubes = numbers.map{$0 * $0 * $0}.filter{$0 >= 0}

在任何二元或三元运算符的两边

还有以下的情况:
✅
var x = 5

func sum(_ numbers: [Int], initialValue: Int = 0) {
  // ...
}

❌ 
var x=5

func sum(_ numbers: [Int], initialValue: Int=0) {
  // ...
}
✅
func sayHappyBirthday(to person: NameProviding & AgeProviding) {
  // ...
}

❌ 
func sayHappyBirthday(to person: NameProviding&AgeProviding) {
  // ...
}
✅
static func == (lhs: MyType, rhs: MyType) -> Bool {
  // ...
}

❌
static func ==(lhs: MyType, rhs: MyType) -> Bool {
  // ...
}
✅
func sum(_ numbers: [Int]) -> Int {
  // ...
}

❌
func sum(_ numbers: [Int])->Int {
  // ...
}
✅
let width = view.bounds.width

❌
let width = view . bounds . width
✅
for number in 1...5 {
  // ...
}

❌
let substring = string[index..<string.endIndex]
for number in 1 ... 5 {
  // ...
}

❌
let substring = string[index ..< string.endIndex]

参数列表、数组、tuple、字典里的逗号后面有一个空格

✅
let numbers = [1, 2, 3]

❌
let numbers = [1,2,3]
let numbers = [1 ,2 ,3]
let numbers = [1 , 2 , 3]

冒号的后面有一个空格

✅
// 类型声明
struct HashTable: Collection {
  // ...
}

struct AnyEquatable<Wrapped: Equatable>: Equatable {
  // ...
}

// 参数标签
let tuple: (x: Int, y: Int)

func sum(_ numbers: [Int]) {
  // ...
}

// 变量声明
let number: Int = 5

// 字典声明
var nameAgeMap: [String: Int] = []

// 字典字面量
let nameAgeMap = ["Ed": 40, "Timmy": 9]

代码后的注释符号 // 与代码有两个空格距离

✅
let initialFactor = 2  // Warm up the modulator.
❌
let initialFactor = 2 //    Warm up the modulator.

表示字典、数组字面量的中括号外面有一个空格

✅
let numbers = [1, 2, 3]
❌
let numbers = [ 1, 2, 3 ]

禁止变量、属性水平对齐

水平对齐是明确禁止的,除非是在写明显的表格数据时,省略对齐会损害可读性。引入水平对齐后,如果添加一个新的成员可能会需要其他成员再对齐一次,这给维护增加了负担。
✅
struct DataPoint {
  var value: Int
  var primaryColor: UIColor
}
❌
struct DataPoint {
  var value:        Int
  var primaryColor: UIColor
}

空白行(垂直方向的空白)

空白行出现在以下几种情况:

括号

最顶级的 if、guard、while、switch 的条件不使用括号。
✅
if x == 0 {
  print("x is zero")
}

if (x == 0 || y == 1) && z == 2 {
  print("...")
}

❌
if (x == 0) {
  print("x is zero")
}

if ((x == 0 || y == 1) && z == 2) {
  print("...")
}
在有复杂的条件表达式,只有作者和 review 的人同时认为省略括号不会影响代码的可读性才会省略。不能假设每个读者都完全了解对 swift 的运算符优先级,所以这种情况下的括号提示用户的计算优先级是合理的。