├── 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 | 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 |
如果可以,省略只读属性和 subscriptget 关键字 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 或 deinitializers),不然就用 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 |

默认 classfinal 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 | --------------------------------------------------------------------------------