[关闭]
@Rookie 2022-06-22T07:29:43.000000Z 字数 5730 阅读 1822

swift代码规范

iOS开发


一、命名

1.类型

  1. enum Planet {
  2. case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
  3. }
  4. struct Person {
  5. var mobileNo: String
  6. }

2.协议

根据苹果接口设计指导准则,协议名称用来描述一些东西是什么的时候是名词,例如:Collection, WidgetFactory。若协议名称用来描述能力应该以 -ing, -able, 或 -ible 结尾,例如:Equatable, Resizing。

3.类前缀

  1. import SomeModule
  2. let myClass = SomeModule.UsefulClass()

4.参数命名

委托

在定义委托方法时,第一个未命名参数应是委托数据源。
正确代码:

  1. func namePickerView(_ namePickerView: NamePickerView, didSelectName name: String)
  2. func namePickerViewShouldReload(_ namePickerView: NamePickerView) -> Bool

错误代码:

  1. func didSelectName(namePicker: NamePickerViewController, name: String)
  2. func namePickerShouldReload() -> Bool

泛型

泛型类参数应具有描述性,遵守“大骆驼命名法”。如果一个参数名没有具体的含义,可以使用传统单大写字符,如T, U, 或V等。
正确代码:

  1. struct Stack<Element>{ ... }
  2. func writeTo <Target: OutputStream>(to Target: inout Target)
  3. func swap(_ a: inout T, _ b: inout T)

错误代码:

  1. struct Stack<T>{ ... }
  2. func write<target: OutputStream> (to target: inout target)
  3. func swap<Thing>(_ a: inout Thing, _ b: inout Thing)

二、代码逻辑

1.类型推断

尽量使用类型推断以减少多余的冗余类型信息,例如:
正确的写法:

  1. let currentLocation = Location()

错误的写法:

  1. let currentLocation: Location = Location()

2.self推断

  1. class BoardLocation {
  2. let row: Int, column: Int
  3. init(row: Int, column: Int) {
  4. self.row = row
  5. self.column = column
  6. let closure = {
  7. print(self.row)
  8. }
  9. }
  10. }

3.常量

  1. struct PhysicsModel {
  2. static var speedOfLightInAVacuum = 299_792_458
  3. }
  4. class Spaceship {
  5. static let topSpeed = PhysicsModel.speedOfLightInAVacuum
  6. var speed: Double
  7. func fullSpeedAhead() {
  8. speed = Spaceship.topSpeed
  9. }
  10. }

4.计算型类型属性

正确代码:

  1. class Example {
  2. var age: UInt32 {
  3. return arc4random()
  4. }
  5. }

错误代码:

  1. class Example {
  2. var age: UInt32 {
  3. get {
  4. return arc4random()
  5. }
  6. }
  7. }
  1. class Person {
  2. var age: Int {
  3. get {
  4. return Int(arc4random())
  5. }
  6. set {
  7. print("That's not your age.")
  8. }
  9. }
  10. }

5.单例

Swift中单例很简单,Swift 的 runtime 会保证单例的创建并且采用线程安全的方式访问:

  1. class ControversyManager {
  2. static let sharedInstance = ControversyManager()
  3. }

单例通常只需要访问"sharedInstance"的静态属性,除非你有不得已的原因去重命名它。注意,不要用静态函数或者全局函数去访问你的单例。

6.错误处理

可以使用do/try/catch机制,避免使用try!try?

7.可选值

8.扩展声明周期

用 [weak self] 和 guard let strongSelf = self else { return } 模式扩展生命周期。用 [weak self] 比 [unowned self] 更好。
正确代码:

  1. resource.request().onComplete { [weak self] response in
  2. guard let strongSelf = self else { return }
  3. let model = strongSelf.updateModel(response)
  4. strongSelf.updateUI(model)
  5. }

错误代码:

  1. // might crash if self is released before response returns
  2. resource.request().onComplete { [unowned self] response in
  3. let model = self.updateModel(response)
  4. self.updateUI(model)
  5. }
  1. // deallocate could happen between updating the model and updating UI
  2. resource.request().onComplete { [weak self] response in
  3. let model = self?.updateModel(response)
  4. self?.updateUI(model)
  5. }

三、代码结构

1.注释

2.缩进

遵守Xcode内置的缩进格式

3.类型

优先使用Swift原生类型,可以根据需要使用Objective-C提供的方法,因为Swift提供了到Objective-C的桥接 。
正确代码:

  1. let width = 120.0 // Double
  2. let widthString = (width as NSNumber).stringValue // String

错误代码:

  1. let width: NSNumber = 120.0 // NSNumber
  2. let widthString: NSString=width.stringValue // NSString

4.协议一致性

当一个对象要实现协议一致性时,推荐使用 extension 隔离协议中的方法集,这样让相关方法和协议集中显示在一起,也简化了类支持一个协议和实现相关方法的流程。
正确代码:

  1. class MyViewcontroller: UIViewController {
  2. // 方法
  3. }
  4. extension MyViewcontroller: UITableViewDataSource {
  5. // UITableViewDataSource 方法
  6. }
  7. extension MyViewcontroller: UIScrollViewDelegate {
  8. // UIScrollViewDelegate 方法
  9. }

错误代码:

  1. class MyViewcontroller: UIViewController, UITableViewDataSource, UIScrollViewDelegate {
  2. // 所有的方法
  3. }

5.良好的类定义

  1. final class Circle: Shape {
  2. var x: Int, y: Int
  3. var radius: Double
  4. var diameter: Double{
  5. get {
  6. returnradius * 2
  7. }
  8. set {
  9. radius=newValue/2
  10. }
  11. }
  12. init(x: Int, y: Int, radius: Double) {
  13. self.x = x
  14. self.y = y
  15. self.radius = radius
  16. }
  17. convenience init(x: Int, y: Int, diameter: Double) {
  18. self.init(x: x, y: y, radius: diameter/2)
  19. }
  20. func describe() -> String{
  21. return"I am a circle at\(centerString())with an area of\(computeArea())"
  22. }
  23. override func computeArea() -> Double{
  24. return M_PI * radius * radius
  25. }
  26. private func centerString()->String{
  27. return "(\(x),\(y))"
  28. }
  29. }

6.控制流程

  1. for _ in 0..<3 {
  2. print("Hello three times")
  3. }
  4. for(index, person) in attendeeList.enumerate() {
  5. print("\(person)is at position #\(index)")
  6. }
  7. for index in 0.stride(from: 0, to: items.count, by: 2) {
  8. print(index)
  9. }
  10. for index in (0...3).reverse() {
  11. print(index)
  12. }

错误代码:

  1. var i=0
  2. while i<3 {
  3. print("Hello three times")
  4. i+=1
  5. }
  6. var i=0
  7. while i<3 {
  8. let person = attendeeList[i]
  9. print("\(person)is at position #\(i)")
  10. i+=1
  11. }

7.黄金路径

当编码遇到条件判断时,左边的距离是黄金路径或幸福路径,因为路径越短,速度越快。不要嵌套if循环,多个返回语句是可以的。guard 就为此而生的。
正确代码:

  1. func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {
  2. guard let context = context else {throwFFTError.NoContext }
  3. guard let inputData = inputData else { throwFFTError.NoInputData }
  4. //计算frequencies
  5. return frequencies
  6. }

错误代码:

  1. func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {
  2. if let context = context {
  3. if let inputData = inputData {
  4. // 计算frequencies
  5. return frequencies
  6. } else {
  7. throwFFTError.NoInputData
  8. }
  9. } else {
  10. throwFFTError.NoContext
  11. }
  12. }

当有多个条件需要用 guard 或 if let 解包,可用复合语句避免嵌套。

  1. guard let number1=number1, number2=number2, number3=number3 else{
  2. fatalError("impossible")
  3. }
  4. // 处理number

8.语法糖

  1. //对空的数据和字典,使用类型注解
  2. var names: [String] = []
  3. var lookup: [String: Int] = [:]
  4. var deviceModels: [String]
  5. var employees: [Int:String]
  6. var faxNumber: Int?

9.函数

自由函数不依附于任何类或类型,应该节制地使用。
正确代码:

  1. let sorted = items.mergeSort() // 易发现性
  2. rocket.launch() // 可读性

错误代码:

  1. let sorted = mergeSort(items)// 不易被发现
  2. launch(&rocket)

天然的自由函数:

  1. let value = max(x,y,z) // another free function that feels natural

参考链接:
最详尽的 Swift 代码规范指南
Swift 3.0 编码规范
17条 Swift 最佳实践规范
一份比较通用的iOS代码规范,包括Objective-C和Swift
Swift 编码规范(中文)

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注