├── CONTRIBUTING.md
├── LICENSE
├── README.md
└── README_CN.md
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | If you want to suggest a change or addition that will help accomplish
2 | [the goals](README.md) of this style guide, please open a pull request that:
3 |
4 | 1. Explains the guideline
5 | 1. Demonstrates the guideline with more-or-less valid example code
6 | 1. Justifies the guideline by explaining the rationale behind it
7 |
8 | Just note that all suggestions are open to discussion and debate! :smile:
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | CC0 1.0 Universal
2 |
3 | Statement of Purpose
4 |
5 | The laws of most jurisdictions throughout the world automatically confer
6 | exclusive Copyright and Related Rights (defined below) upon the creator and
7 | subsequent owner(s) (each and all, an "owner") of an original work of
8 | authorship and/or a database (each, a "Work").
9 |
10 | Certain owners wish to permanently relinquish those rights to a Work for the
11 | purpose of contributing to a commons of creative, cultural and scientific
12 | works ("Commons") that the public can reliably and without fear of later
13 | claims of infringement build upon, modify, incorporate in other works, reuse
14 | and redistribute as freely as possible in any form whatsoever and for any
15 | purposes, including without limitation commercial purposes. These owners may
16 | contribute to the Commons to promote the ideal of a free culture and the
17 | further production of creative, cultural and scientific works, or to gain
18 | reputation or greater distribution for their Work in part through the use and
19 | efforts of others.
20 |
21 | For these and/or other purposes and motivations, and without any expectation
22 | of additional consideration or compensation, the person associating CC0 with a
23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
25 | and publicly distribute the Work under its terms, with knowledge of his or her
26 | Copyright and Related Rights in the Work and the meaning and intended legal
27 | effect of CC0 on those rights.
28 |
29 | 1. Copyright and Related Rights. A Work made available under CC0 may be
30 | protected by copyright and related or neighboring rights ("Copyright and
31 | Related Rights"). Copyright and Related Rights include, but are not limited
32 | to, the following:
33 |
34 | i. the right to reproduce, adapt, distribute, perform, display, communicate,
35 | and translate a Work;
36 |
37 | ii. moral rights retained by the original author(s) and/or performer(s);
38 |
39 | iii. publicity and privacy rights pertaining to a person's image or likeness
40 | depicted in a Work;
41 |
42 | iv. rights protecting against unfair competition in regards to a Work,
43 | subject to the limitations in paragraph 4(a), below;
44 |
45 | v. rights protecting the extraction, dissemination, use and reuse of data in
46 | a Work;
47 |
48 | vi. database rights (such as those arising under Directive 96/9/EC of the
49 | European Parliament and of the Council of 11 March 1996 on the legal
50 | protection of databases, and under any national implementation thereof,
51 | including any amended or successor version of such directive); and
52 |
53 | vii. other similar, equivalent or corresponding rights throughout the world
54 | based on applicable law or treaty, and any national implementations thereof.
55 |
56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of,
57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
59 | and Related Rights and associated claims and causes of action, whether now
60 | known or unknown (including existing as well as future claims and causes of
61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum
62 | duration provided by applicable law or treaty (including future time
63 | extensions), (iii) in any current or future medium and for any number of
64 | copies, and (iv) for any purpose whatsoever, including without limitation
65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
66 | the Waiver for the benefit of each member of the public at large and to the
67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver
68 | shall not be subject to revocation, rescission, cancellation, termination, or
69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work
70 | by the public as contemplated by Affirmer's express Statement of Purpose.
71 |
72 | 3. Public License Fallback. Should any part of the Waiver for any reason be
73 | judged legally invalid or ineffective under applicable law, then the Waiver
74 | shall be preserved to the maximum extent permitted taking into account
75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
76 | is so judged Affirmer hereby grants to each affected person a royalty-free,
77 | non transferable, non sublicensable, non exclusive, irrevocable and
78 | unconditional license to exercise Affirmer's Copyright and Related Rights in
79 | the Work (i) in all territories worldwide, (ii) for the maximum duration
80 | provided by applicable law or treaty (including future time extensions), (iii)
81 | in any current or future medium and for any number of copies, and (iv) for any
82 | purpose whatsoever, including without limitation commercial, advertising or
83 | promotional purposes (the "License"). The License shall be deemed effective as
84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the
85 | License for any reason be judged legally invalid or ineffective under
86 | applicable law, such partial invalidity or ineffectiveness shall not
87 | invalidate the remainder of the License, and in such case Affirmer hereby
88 | affirms that he or she will not (i) exercise any of his or her remaining
89 | Copyright and Related Rights in the Work or (ii) assert any associated claims
90 | and causes of action with respect to the Work, in either case contrary to
91 | Affirmer's express Statement of Purpose.
92 |
93 | 4. Limitations and Disclaimers.
94 |
95 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
96 | surrendered, licensed or otherwise affected by this document.
97 |
98 | b. Affirmer offers the Work as-is and makes no representations or warranties
99 | of any kind concerning the Work, express, implied, statutory or otherwise,
100 | including without limitation warranties of title, merchantability, fitness
101 | for a particular purpose, non infringement, or the absence of latent or
102 | other defects, accuracy, or the present or absence of errors, whether or not
103 | discoverable, all to the greatest extent permissible under applicable law.
104 |
105 | c. Affirmer disclaims responsibility for clearing rights of other persons
106 | that may apply to the Work or any use thereof, including without limitation
107 | any person's Copyright and Related Rights in the Work. Further, Affirmer
108 | disclaims responsibility for obtaining any necessary consents, permissions
109 | or other rights required for any use of the Work.
110 |
111 | d. Affirmer understands and acknowledges that Creative Commons is not a
112 | party to this document and has no duty or obligation with respect to this
113 | CC0 or use of the Work.
114 |
115 | For more information, please see
116 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [中文版](https://github.com/Artwalk/swift-style-guide/blob/master/README_CN.md)
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | 郑重声明:
2 | 如果看不懂,估计是我翻译的不好
3 | 233333
4 |
5 | 哪里不对或者不准确的,(我把原文贴上来了,点击左侧三角形就能展开用来对照 2015-12-13)
6 | 若能指出,感激不尽~~~
7 |
8 | 如果没能及时更新,可能比较忙,或者比较懒 →_→
9 | 翻译后可以 email 或 `pull request`
10 |
11 | ----
12 |
13 |
14 | Swift 编码规范
15 | A guide to our Swift style and conventions.
16 |
17 |
18 | 按大概的先后顺序,本文尝试做到以下几点:
19 | This is an attempt to encourage patterns that accomplish the following goals (in
20 | rough priority order):
21 |
22 |
23 | 1. 增进精确,减少程序员犯错的可能
Increased rigor, and decreased likelihood of programmer error
24 | 1. 明确意图
Increased clarity of intent
25 | 1. 减少冗余
Reduced verbosity
26 | 1. 减少关于美的争论
Fewer debates about aesthetics
27 |
28 |
29 | 如果你有什么建议,请看我们的 贡献导引,然后开个 pull request
. :zap:
30 |
31 |
32 | If you have suggestions, please see our [contribution guidelines](CONTRIBUTING.md),
33 | then open a pull request. :zap:
34 |
35 |
36 | ----
37 |
38 | 留空白
Whitespace
39 |
40 |
41 | 用 tab,而非 空格
Tabs, not spaces.
42 | 文件结束时留一空行
End files with a newline.
43 | 用足够的空行把代码分割成合理的块
Make liberal use of vertical whitespace to divide code into logical chunks.
44 | 不要在一行结尾留下空白
Don’t leave trailing whitespace.
45 | 千万别在空行留下缩进
Not even leading indentation on blank lines.
46 |
47 |
48 |
49 |
50 | 能用 let
尽量用 let
而不是 var
51 |
52 | Prefer `let`-bindings over `var`-bindings wherever possible
53 |
54 |
55 |
56 |
57 | 尽可能的用 let foo = ...
而不是 var foo = ...
(并且包括你疑惑的时候)。万不得已的时候,再用 var
(就是说:你 知道 这个值会改变,比如:有 weak
修饰的存储变量)。
58 |
59 |
60 | 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).
61 |
62 |
63 |
64 |
65 | 理由: 这俩关键字 无论意图还是意义 都很清楚了,但是 let
可以产生安全清晰的代码。
66 |
67 |
68 | _Rationale:_ The intent and meaning of both keywords are clear, but *let-by-default* results in safer and clearer code.
69 |
70 |
71 |
72 |
73 |
74 |
75 | let
保障它的值的永远不会变,对程序猿也是个 清晰的标记。因此对于它的用法,之后的代码可以做个强而有力的推断。
76 |
77 | 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.
78 |
79 |
80 |
81 |
82 | 理解代码也更容易了。不然一旦你用了 var
,还要去推测值会不会变,这时候你就不得不人肉去检查。
83 |
84 |
85 | 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.
86 |
87 |
88 |
89 |
90 | 相应地,无论何时你看到 var
,就假设它会变,并问自己为啥。
91 |
92 |
93 | Accordingly, whenever you see a `var` identifier being used, assume that it will change and ask yourself why.
94 |
95 |
96 |
97 | 尽早地 return
或者 break
98 |
99 | Return and break early
100 |
101 |
102 | 当你遇到某些操作需要通过条件判断去执行,应当尽早地退出判断条件:你不应该用下面这种写法
103 |
104 | When you have to meet certain criteria to continue execution, try to exit early. So, instead of this:
105 |
106 |
107 | ```swift
108 | if n.isNumber {
109 | // Use n here
110 | } else {
111 | return
112 | }
113 | ```
114 |
115 | 用这个:
use this:
116 |
117 | ```swift
118 | guard n.isNumber else {
119 | return
120 | }
121 | // Use n here
122 | ```
123 |
124 |
125 | 或者你也可以用 if
声明,但是我们推荐你使用 guard
126 |
127 | You can also do it with `if` statement, but using `guard` is prefered
128 |
129 |
130 |
131 | 理由: 你一但声明 guard
编译器会强制要求你和 return
, break
或者 continue
一起搭配使用,否则会产生一个编译时的错误。
132 |
133 | because `guard` statement without `return`, `break` or `continue` produces a compile-time error, so exit is guaranteed.
134 |
135 |
136 | 避免对 可选类型 强解包
Avoid Using Force-Unwrapping of Optionals
137 |
138 | 如果你有个 FooType?
或 FooType!
的 foo
,尽量不要强行展开它(foo!
)以得到它的关联值。
139 |
140 | 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.
141 |
142 |
143 | 取而代之的,推荐这样:
Instead, prefer this:
144 |
145 | ```swift
146 | if let foo = foo {
147 | // Use unwrapped `foo` value in here
148 | } else {
149 | // If appropriate, handle the case where the optional is nil
150 | }
151 | ```
152 |
153 | 或者使用可选链,比如:
154 |
155 | Alternatively, you might want to use Swift's Optional Chaining in some of these cases, such as:
156 |
157 |
158 | ```swift
159 | // Call the function if `foo` is not nil. If `foo` is nil, ignore we ever tried to make the call
160 | foo?.callSomethingIfFooIsNotNil()
161 | ```
162 |
163 | 理由: if let
绑定可选类型产生了更安全的代码,强行展开很可能导致运行时崩溃。
164 |
165 | _Rationale:_ Explicit `if let`-binding of optionals results in safer code. Force unwrapping is more prone to lead to runtime crashes.
166 |
167 |
168 | 避免隐式解析的可选类型
Avoid Using Implicitly Unwrapped Optionals
169 |
170 | 如果 foo 可能为 nil
,尽可能的用 let foo: FooType?
代替 let foo: FooType!
(注意:一般情况下,?
可以代替 !
)
171 |
172 | 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 `!`).
173 |
174 |
175 | 理由: 明确的可选类型产生了更安全的代码。隐式解析的可选类型也可能会挂。
176 |
177 | _Rationale:_ Explicit optionals result in safer code. Implicitly unwrapped optionals have the potential of crashing at runtime.
178 |
179 |
180 | 对于只读属性和 subscript
,选用隐式的 getters 方法
181 |
182 | Prefer implicit getters on read-only properties and subscripts
183 |
184 |
185 | 如果可以,省略只读属性和 subscript
的 get
关键字
186 |
187 | When possible, omit the `get` keyword on read-only computed properties and
188 | read-only subscripts.
189 |
190 | 所以应该这样写:
So, write these:
191 |
192 | ```swift
193 | var myGreatProperty: Int {
194 | return 4
195 | }
196 |
197 | subscript(index: Int) -> T {
198 | return objects[index]
199 | }
200 | ```
201 |
202 | ……而不是:
… not these:
203 |
204 | ```swift
205 | var myGreatProperty: Int {
206 | get {
207 | return 4
208 | }
209 | }
210 |
211 | subscript(index: Int) -> T {
212 | get {
213 | return objects[index]
214 | }
215 | }
216 | ```
217 |
218 | 理由: 第一个版本的代码意图已经很清楚了,并且用了更少的代码
219 |
220 | _Rationale:_ The intent and meaning of the first version are clear, and results in less code.
221 |
222 |
223 | 对于顶级定义,永远明确的列出权限控制
Always specify access control explicitly for top-level definitions
224 |
225 | 顶级函数,类型和变量,永远应该有着详尽的权限控制说明符
226 |
227 | Top-level functions, types, and variables should always have explicit access control specifiers:
228 |
229 |
230 | ```swift
231 | public var whoopsGlobalState: Int
232 | internal struct TheFez {}
233 | private func doTheThings(things: [Thing]) {}
234 | ```
235 |
236 | 然而在这些函数/类型的内部,可以在合适的地方使用隐式权限控制:
However, definitions within those can leave access control implicit, where appropriate:
237 |
238 |
239 | ```swift
240 | internal struct TheFez {
241 | var owner: Person = Joshaber()
242 | }
243 | ```
244 |
245 | 理由: 顶级定义指定为 internal
很少有恰当的,要明确的确保经过了仔细的判断。在定义的内部重用同样的权限控制说明符就显得重复,而且默认的通常是合理的。
246 |
247 | _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.
248 |
249 |
250 | 当指定一个类型时,把 冒号和标识符 连在一起
251 |
252 | When specifying a type, always associate the colon with the identifier
253 |
254 |
255 | 当指定标示符的类型时,冒号要紧跟着标示符,然后空一格再写类型
256 |
257 | When specifying the type of an identifier, always put the colon immediately
258 | after the identifier, followed by a space and then the type name.
259 |
260 |
261 | ```swift
262 | class SmallBatchSustainableFairtrade: Coffee { ... }
263 |
264 | let timeToCoffee: NSTimeInterval = 2
265 |
266 | func makeCoffee(type: CoffeeType) -> Coffee { ... }
267 | ```
268 |
269 | 理由: 类型区分号是对于标示符来说的,所以要跟它连在一起。
270 |
271 | _Rationale:_ The type specifier is saying something about the _identifier_ so
272 | it should be positioned with it.
273 |
274 |
275 |
276 |
277 | 此外,指定字典类型时,键类型后紧跟着冒号,接着加一个空格,之后才是值类型。
278 |
279 | 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.
280 |
281 |
282 | ```swift
283 | let capitals: [Country: City] = [sweden: stockholm]
284 | ```
285 |
286 | 需要时才写上 self
287 |
288 | Only explicitly refer to `self` when required
289 |
290 |
291 | 当调用 self
的属性或方法时,默认隐式引用self
:
292 |
293 | When accessing properties or methods on `self`, leave the reference to `self` implicit by default:
294 |
295 |
296 | ```swift
297 | private class History {
298 | var events: [Event]
299 |
300 | func rewrite() {
301 | events = []
302 | }
303 | }
304 | ```
305 |
306 | 必要的时候再加上 self
, 比如在(逃逸)闭包里,或者 参数名冲突了:
307 |
308 | Only include the explicit keyword when required by the language—for example, in a closure, or when parameter names conflict:
309 |
310 |
311 | ```swift
312 | extension History {
313 | init(events: [Event]) {
314 | self.events = events
315 | }
316 |
317 | var whenVictorious: () -> () {
318 | return {
319 | self.rewrite()
320 | }
321 | }
322 | }
323 | ```
324 |
325 | 原因: 在闭包里用 self
更加凸显它捕获 self
的语义,别处避免了冗长
326 |
327 | _Rationale:_ This makes the capturing semantics of `self` stand out more in closures, and avoids verbosity elsewhere.
328 |
329 |
330 | 首选 struct
而非 class
331 |
332 | Prefer structs over classes
333 |
334 |
335 | 除非你需要 class
才能提供的功能(比如 identity 或 deinit
ializers),不然就用 struct
336 |
337 | Unless you require functionality that can only be provided by a class (like identity or deinitializers), implement a struct instead.
338 |
339 |
340 | 要注意到继承通常 不 是用 类 的好理由,因为 多态 可以通过 协议 实现,重用 可以通过 组合 实现。
341 |
342 | 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.
343 |
344 |
345 | 比如,这个类的分级
346 |
347 | For example, this class hierarchy:
348 |
349 |
350 | ```swift
351 | class Vehicle {
352 | let numberOfWheels: Int
353 |
354 | init(numberOfWheels: Int) {
355 | self.numberOfWheels = numberOfWheels
356 | }
357 |
358 | func maximumTotalTirePressure(pressurePerWheel: Float) -> Float {
359 | return pressurePerWheel * Float(numberOfWheels)
360 | }
361 | }
362 |
363 | class Bicycle: Vehicle {
364 | init() {
365 | super.init(numberOfWheels: 2)
366 | }
367 | }
368 |
369 | class Car: Vehicle {
370 | init() {
371 | super.init(numberOfWheels: 4)
372 | }
373 | }
374 | ```
375 |
376 | 可以重构成酱紫:
377 |
378 | could be refactored into these definitions:
379 |
380 |
381 | ```swift
382 | protocol Vehicle {
383 | var numberOfWheels: Int { get }
384 | }
385 |
386 | func maximumTotalTirePressure(vehicle: Vehicle, pressurePerWheel: Float) -> Float {
387 | return pressurePerWheel * Float(vehicle.numberOfWheels)
388 | }
389 |
390 | struct Bicycle: Vehicle {
391 | let numberOfWheels = 2
392 | }
393 |
394 | struct Car: Vehicle {
395 | let numberOfWheels = 4
396 | }
397 | ```
398 |
399 | 理由: 值类型更简单,容易分析,并且 let
关键字的行为符合预期。
400 |
401 | _Rationale:_ Value types are simpler, easier to reason about, and behave as expected with the `let` keyword.
402 |
403 |
404 | 默认 class
为 final
405 |
406 | Make classes `final` by default
407 |
408 |
409 | class
应该用 final
修饰,并且只有在继承的有效需求已被确定时候才能去使用子类。即便在这种情况(前面提到的使用继承的情况)下,根据同样的规则(class
应该用 final
修饰的规则),类中的定义(属性和方法等)也要尽可能的用 final
来修饰
410 |
411 |
412 | 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.
413 |
414 |
415 | 理由: 组合通常比继承更合适,选择使用继承则很可能意味着在做出决定时需要更多的思考。
416 |
417 | _Rationale:_ Composition is usually preferable to inheritance, and opting _in_ to inheritance hopefully means that more thought will be put into the decision.
418 |
419 |
420 | 能不写类型参数的就别写了
421 |
422 | Omit type parameters where possible
423 |
424 |
425 | 当对接收者来说一样时,参数化类型的方法可以省略接收者的类型参数。比如:
426 |
427 | Methods of parameterized types can omit type parameters on the receiving type when they’re identical to the receiver’s. For example:
428 |
429 |
430 | ```swift
431 | struct Composite {
432 | …
433 | func compose(other: Composite) -> Composite {
434 | return Composite(self, other)
435 | }
436 | }
437 | ```
438 |
439 | 可以改成这样:
could be rendered as:
440 |
441 | ```swift
442 | struct Composite {
443 | …
444 | func compose(other: Composite) -> Composite {
445 | return Composite(self, other)
446 | }
447 | }
448 | ```
449 |
450 | 理由: 省略多余的类型参数让意图更清晰,并且通过对比,让返回值为不同的类型参数的情况也清楚了很多。
451 |
452 | _Rationale:_ Omitting redundant type parameters clarifies the intent, and makes it obvious by contrast when the returned type takes different type parameters.
453 |
454 |
455 | 定义操作符 两边留空格
456 |
457 | Use whitespace around operator definitions
458 |
459 |
460 | 当定义操作符时,两边留空格。不要酱紫:
461 |
462 | Use whitespace around operators when defining them. Instead of:
463 |
464 |
465 | ```swift
466 | func <|(lhs: Int, rhs: Int) -> Int
467 | func <|<(lhs: A, rhs: A) -> A
468 | ```
469 |
470 | 应该写:
write:
471 |
472 | ```swift
473 | func <| (lhs: Int, rhs: Int) -> Int
474 | func <|< (lhs: A, rhs: A) -> A
475 | ```
476 |
477 | 理由: 操作符 由标点字符组成,当立即连着类型或者参数值,会让代码非常难读。加上空格分开他们就清晰了
478 |
479 | _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.
480 |
481 |
482 | ### 其他语言
483 |
484 | * [English Version](https://github.com/github/swift-style-guide)
485 | * [日本語版](https://github.com/jarinosuke/swift-style-guide/blob/master/README_JP.md)
486 | * [한국어판](https://github.com/minsOne/swift-style-guide/blob/master/README_KR.md)
487 | * [Versión en Español](https://github.com/antoniosejas/swift-style-guide/blob/spanish/README-ES.md)
488 | * [Versão em Português do Brasil](https://github.com/fernandocastor/swift-style-guide/blob/master/README-PTBR.md)
489 | * [فارسی](https://github.com/mohpor/swift-style-guide/blob/Persian/README-FA.md)
490 |
--------------------------------------------------------------------------------