Skip to content

Latest commit

 

History

History
489 lines (347 loc) · 17.5 KB

README_CN.md

File metadata and controls

489 lines (347 loc) · 17.5 KB

郑重声明: 如果看不懂,估计是我翻译的不好 233333

哪里不对或者不准确的,(我把原文贴上来了,点击左侧三角形就能展开用来对照 2015-12-13) 若能指出,感激不尽~~~

如果没能及时更新,可能比较忙,或者比较懒 →_→ 翻译后可以 email 或 pull request


Swift 编码规范 A guide to our Swift style and conventions.

按大概的先后顺序,本文尝试做到以下几点: This is an attempt to encourage patterns that accomplish the following goals (in rough priority order):
  1. 增进精确,减少程序员犯错的可能Increased rigor, and decreased likelihood of programmer error
  2. 明确意图Increased clarity of intent
  3. 减少冗余Reduced verbosity
  4. 减少关于美的争论Fewer debates about aesthetics
如果你有什么建议,请看我们的 贡献导引,然后开个 pull request. ⚡

If you have suggestions, please see our contribution guidelines, then open a pull request. ⚡


留空白Whitespace

  • 用 tab,而非 空格Tabs, not spaces.
  • 文件结束时留一空行End files with a newline.
  • 用足够的空行把代码分割成合理的块Make liberal use of vertical whitespace to divide code into logical chunks.
  • 不要在一行结尾留下空白Don’t leave trailing whitespace.
    • 千万别在空行留下缩进Not even leading indentation on blank lines.

能用 let 尽量用 let 而不是 var

Prefer let-bindings over var-bindings wherever possible

尽可能的用 let foo = ... 而不是 var foo = ... (并且包括你疑惑的时候)。万不得已的时候,再用 var (就是说:你 知道 这个值会改变,比如:有 weak 修饰的存储变量)。

Use let foo = … over var foo = … wherever possible (and when in doubt). Only use var if you absolutely have to (i.e. you know that the value might change, e.g. when using the weak storage modifier).

理由: 这俩关键字 无论意图还是意义 都很清楚了,但是 let 可以产生安全清晰的代码。

Rationale: The intent and meaning of both keywords are clear, but let-by-default results in safer and clearer code.


let 保障它的值的永远不会变,对程序猿也是个 清晰的标记。因此对于它的用法,之后的代码可以做个强而有力的推断。

A let-binding guarantees and clearly signals to the programmer that its value will never change. Subsequent code can thus make stronger assumptions about its usage.

理解代码也更容易了。不然一旦你用了 var,还要去推测值会不会变,这时候你就不得不人肉去检查。

It becomes easier to reason about code. Had you used var while still making the assumption that the value never changed, you would have to manually check that.

相应地,无论何时你看到 var,就假设它会变,并问自己为啥。

Accordingly, whenever you see a var identifier being used, assume that it will change and ask yourself why.

尽早地 return 或者 break

Return and break early

当你遇到某些操作需要通过条件判断去执行,应当尽早地退出判断条件:你不应该用下面这种写法

When you have to meet certain criteria to continue execution, try to exit early. So, instead of this:

if n.isNumber {
	// Use n here
} else {
	return
}
用这个:use this:
guard n.isNumber else {
	return
}
// Use n here
或者你也可以用 if 声明,但是我们推荐你使用 guard

You can also do it with if statement, but using guard is prefered

理由: 你一但声明 guard 编译器会强制要求你和 return, break 或者 continue 一起搭配使用,否则会产生一个编译时的错误。

because guard statement without return, break or continue produces a compile-time error, so exit is guaranteed.

避免对 可选类型 强解包Avoid Using Force-Unwrapping of Optionals

如果你有个 FooType?FooType!foo,尽量不要强行展开它(foo!)以得到它的关联值。

If you have an identifier foo of type FooType? or FooType!, don't force-unwrap it to get to the underlying value (foo!) if possible.

取而代之的,推荐这样:Instead, prefer this:
if let foo = foo {
	// Use unwrapped `foo` value in here
} else {
	// If appropriate, handle the case where the optional is nil
}
或者使用可选链,比如:

Alternatively, you might want to use Swift's Optional Chaining in some of these cases, such as:

// Call the function if `foo` is not nil. If `foo` is nil, ignore we ever tried to make the call
foo?.callSomethingIfFooIsNotNil()
理由: if let 绑定可选类型产生了更安全的代码,强行展开很可能导致运行时崩溃。

Rationale: Explicit if let-binding of optionals results in safer code. Force unwrapping is more prone to lead to runtime crashes.

避免隐式解析的可选类型Avoid Using Implicitly Unwrapped Optionals

如果 foo 可能为 nil ,尽可能的用 let foo: FooType? 代替 let foo: FooType!(注意:一般情况下,? 可以代替 !

Where possible, use let foo: FooType? instead of let foo: FooType! if foo may be nil (Note that in general, ? can be used instead of !).

理由: 明确的可选类型产生了更安全的代码。隐式解析的可选类型也可能会挂。

Rationale: Explicit optionals result in safer code. Implicitly unwrapped optionals have the potential of crashing at runtime.

对于只读属性和 subscript,选用隐式的 getters 方法

Prefer implicit getters on read-only properties and subscripts

如果可以,省略只读属性和 subscriptget 关键字

When possible, omit the get keyword on read-only computed properties and read-only subscripts.

所以应该这样写:So, write these:
var myGreatProperty: Int {
	return 4
}

subscript(index: Int) -> T {
	return objects[index]
}
……而不是:… not these:
var myGreatProperty: Int {
	get {
		return 4
	}
}

subscript(index: Int) -> T {
	get {
		return objects[index]
	}
}
理由: 第一个版本的代码意图已经很清楚了,并且用了更少的代码

Rationale: The intent and meaning of the first version are clear, and results in less code.

对于顶级定义,永远明确的列出权限控制Always specify access control explicitly for top-level definitions

顶级函数,类型和变量,永远应该有着详尽的权限控制说明符

Top-level functions, types, and variables should always have explicit access control specifiers:

public var whoopsGlobalState: Int
internal struct TheFez {}
private func doTheThings(things: [Thing]) {}
然而在这些函数/类型的内部,可以在合适的地方使用隐式权限控制:However, definitions within those can leave access control implicit, where appropriate:
internal struct TheFez {
	var owner: Person = Joshaber()
}
理由: 顶级定义指定为 internal 很少有恰当的,要明确的确保经过了仔细的判断。在定义的内部重用同样的权限控制说明符就显得重复,而且默认的通常是合理的。

Rationale: It's rarely appropriate for top-level definitions to be specifically internal, and being explicit ensures that careful thought goes into that decision. Within a definition, reusing the same access control specifier is just duplicative, and the default is usually reasonable.

当指定一个类型时,把 冒号和标识符 连在一起

When specifying a type, always associate the colon with the identifier

当指定标示符的类型时,冒号要紧跟着标示符,然后空一格再写类型

When specifying the type of an identifier, always put the colon immediately after the identifier, followed by a space and then the type name.

class SmallBatchSustainableFairtrade: Coffee { ... }

let timeToCoffee: NSTimeInterval = 2

func makeCoffee(type: CoffeeType) -> Coffee { ... }
理由: 类型区分号是对于标示符来说的,所以要跟它连在一起。

Rationale: The type specifier is saying something about the identifier so it should be positioned with it.


此外,指定字典类型时,键类型后紧跟着冒号,接着加一个空格,之后才是值类型。

Also, when specifying the type of a dictionary, always put the colon immediately after the key type, followed by a space and then the value type.

let capitals: [Country: City] = [sweden: stockholm]

需要时才写上 self

Only explicitly refer to self when required

当调用 self 的属性或方法时,默认隐式引用self

When accessing properties or methods on self, leave the reference to self implicit by default:

private class History {
	var events: [Event]

	func rewrite() {
		events = []
	}
}
必要的时候再加上 self, 比如在(逃逸)闭包里,或者 参数名冲突了:

Only include the explicit keyword when required by the language—for example, in a closure, or when parameter names conflict:

extension History {
	init(events: [Event]) {
		self.events = events
	}

	var whenVictorious: () -> () {
		return {
			self.rewrite()
		}
	}
}
原因: 在闭包里用 self 更加凸显它捕获 self 的语义,别处避免了冗长

Rationale: This makes the capturing semantics of self stand out more in closures, and avoids verbosity elsewhere.

首选 struct 而非 class

Prefer structs over classes

除非你需要 class 才能提供的功能(比如 identity 或 deinitializers),不然就用 struct

Unless you require functionality that can only be provided by a class (like identity or deinitializers), implement a struct instead.

要注意到继承通常 是用 类 的好理由,因为 多态 可以通过 协议 实现,重用 可以通过 组合 实现。

Note that inheritance is (by itself) usually not a good reason to use classes, because polymorphism can be provided by protocols, and implementation reuse can be provided through composition.

比如,这个类的分级

For example, this class hierarchy:

class Vehicle {
	let numberOfWheels: Int

	init(numberOfWheels: Int) {
		self.numberOfWheels = numberOfWheels
	}

	func maximumTotalTirePressure(pressurePerWheel: Float) -> Float {
		return pressurePerWheel * Float(numberOfWheels)
	}
}

class Bicycle: Vehicle {
	init() {
		super.init(numberOfWheels: 2)
	}
}

class Car: Vehicle {
	init() {
		super.init(numberOfWheels: 4)
	}
}
可以重构成酱紫:

could be refactored into these definitions:

protocol Vehicle {
	var numberOfWheels: Int { get }
}

func maximumTotalTirePressure(vehicle: Vehicle, pressurePerWheel: Float) -> Float {
	return pressurePerWheel * Float(vehicle.numberOfWheels)
}

struct Bicycle: Vehicle {
	let numberOfWheels = 2
}

struct Car: Vehicle {
	let numberOfWheels = 4
}
理由: 值类型更简单,容易分析,并且 let 关键字的行为符合预期。

Rationale: Value types are simpler, easier to reason about, and behave as expected with the let keyword.

默认 classfinal

Make classes final by default

class 应该用 final 修饰,并且只有在继承的有效需求已被确定时候才能去使用子类。即便在这种情况(前面提到的使用继承的情况)下,根据同样的规则(class 应该用 final 修饰的规则),类中的定义(属性和方法等)也要尽可能的用 final 来修饰

Classes should start as final, and only be changed to allow subclassing if a valid need for inheritance has been identified. Even in that case, as many definitions as possible within the class should be final as well, following the same rules.

理由: 组合通常比继承更合适,选择使用继承则很可能意味着在做出决定时需要更多的思考。

Rationale: Composition is usually preferable to inheritance, and opting in to inheritance hopefully means that more thought will be put into the decision.

能不写类型参数的就别写了

Omit type parameters where possible

当对接收者来说一样时,参数化类型的方法可以省略接收者的类型参数。比如:

Methods of parameterized types can omit type parameters on the receiving type when they’re identical to the receiver’s. For example:

struct Composite<T> {
	
	func compose(other: Composite<T>) -> Composite<T> {
		return Composite<T>(self, other)
	}
}
可以改成这样:could be rendered as:
struct Composite<T> {
	
	func compose(other: Composite) -> Composite {
		return Composite(self, other)
	}
}
理由: 省略多余的类型参数让意图更清晰,并且通过对比,让返回值为不同的类型参数的情况也清楚了很多。

Rationale: Omitting redundant type parameters clarifies the intent, and makes it obvious by contrast when the returned type takes different type parameters.

定义操作符 两边留空格

Use whitespace around operator definitions

当定义操作符时,两边留空格。不要酱紫:

Use whitespace around operators when defining them. Instead of:

func <|(lhs: Int, rhs: Int) -> Int
func <|<<A>(lhs: A, rhs: A) -> A
应该写:write:
func <| (lhs: Int, rhs: Int) -> Int
func <|< <A>(lhs: A, rhs: A) -> A
理由: 操作符 由标点字符组成,当立即连着类型或者参数值,会让代码非常难读。加上空格分开他们就清晰了

Rationale: Operators consist of punctuation characters, which can make them difficult to read when immediately followed by the punctuation for a type or value parameter list. Adding whitespace separates the two more clearly.

其他语言