团队的Swift代码规范,参考Swift Style Guide和Swift 4.0 编码规范,并根据团队实际需要做调整。
一、编码格式
1.1 使用二元运算符(+, -,==, 或->)的前后都需要添加空格
let value = 1 + 2
1.2 在逗号前面不添加空格,后面加一个空格
let titleArray = [1, 2, 3, 4, 5]
1.3 在冒号前面不添加空格,后面添加一个空格。
// 指定类型
let someViewController: SomeViewController
// 字典语法
let ninjaDictionary: [String: AnyObject] = [
"fightLikeDairyFarmer": false,
"disgusting": true
]
// 调用函数
someFunction(someArgument: "Kitten")
// 父类
class SomeViewController: UIViewController {
/* ... */
}
// 协议
extension SomeViewController: UITableViewDataSource {
/* ... */
}
1.3 左大括号不用另起一行
class SomeClass {
func someMethod() {
if x == y {
/* ... */
} else if x == z {
/* ... */
} else {
/* ... */
}
}
/* ... */
}
1.4 判断语句中,只有一个判断条件的时候,不用加括号
if typeValue == 1 {
// code
}
1.5 在访问枚举类型时,使用点语法
enum Direction {
case north
case south
case east
case west
}
let currentDirection = .west
1.6 遵守Xcode内置的缩进格式(格式快捷键:CTRL-i),当声明的一个函数需要跨多行时,推荐使用Xcode默认格式。
// Xcode针对跨多行函数声明缩进
func myFunctionWithManyParameters(parameterOne: String,
parameterTwo: String,
parameterThree: String) {
// Xcode会自动缩进
print("\(parameterOne) \(parameterTwo) \(parameterThree)")
}
// Xcode针对多行 if 语句的缩进
if myFirstVariable > (mySecondVariable + myThirdVariable) &&
myFourthVariable == .SomeEnumValue {
// Xcode会自动缩进
print("Hello, World!")
}
1.7 view controller的方法顺序,根据生命周期排列。且在viewWillAppear、viewDidAppear中,需要先调用super方法。在viewWillDisappear、viewDidDisappear中,需最后调用super方法
override func viewDidLoad() {
super.viewDidLoad()
// your code
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// your code
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// your code
}
override func viewWillDisappear(_ animated: Bool) {
// your code
super.viewWillDisappear(animated)
}
override func viewDidDisappear(_ animated: Bool) {
// your code
super.viewDidDisappear(animated)
}
deinit {
// your code
}
// other function...
二、命名规范
2.1 常量,变量,函数,方法的命名规则使用小驼峰规则,首字母小写,类型名使用大驼峰规则,首字母大写。
class MyClass: class {
let myImageView: UIImageView
let myName: String
}
2.2 当命名里出现缩写词时,缩写词要么全部大写,要么全部小写,以首字母大小写为准。(服务器返回model的key除外)
let htmlString = "https://www.baidu.com"
let urlString: URLString
let userID: UserID
class HTMLModel {
//
}
2.3 bool类型命名时,使用is作为前缀(该条非强制,仅供参考)
var isMine: Bool = false
2.4 命名应该具有描述性
// 推荐
class RoundAnimatingButton: UIButton { /* ... */ }
// 不推荐
class CustomButton: UIButton { /* ... */ }
2.5 不要简写命名,或用单个字母命名。(允许使用常见的缩写,如html、url、id等)
// 推荐
class RoundAnimatingButton: UIButton {
let animationDuration: NSTimeInterval
func startAnimating() {
let firstSubview = subviews.first
}
}
// 不推荐
class RoundAnimating: UIButton {
let aniDur: NSTimeInterval
func srtAnmating() {
let v = subviews.first
}
}
2.6 如果原有命名不能明显表明类型,则属性命名内要包括类型信息。
// 推荐
class ConnectionTableViewCell: UITableViewCell {
let personImageView: UIImageView
let animationDuration: NSTimeInterval
// 作为属性名的firstName,很明显是字符串类型,所以不用在命名里不用包含String
let firstName: String
let popupViewController: UIViewController
// 如果需要使用UIViewController的子类,如TableViewController, CollectionViewController, SplitViewController, 等,需要在命名里标名类型。
let popupTableViewController: UITableViewController
// 当使用outlets时, 确保命名中标注类型。
@IBOutlet weak var submitButton: UIButton!
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var nameLabel: UILabel!
}
// 不推荐
class ConnectionTableViewCell: UITableViewCell {
// 这个不是 UIImage, 不应该以Image 为结尾命名。
let personImage: UIImageView
// 这个不是String,应该命名为 textLabel
let text: UILabel
// animation 不能清晰表达出时间间隔
// 建议使用 animationDuration 或 animationTimeInterval
let animation: NSTimeInterval
// transition 不能清晰表达出是String
// 建议使用 transitionText 或 transitionString
let transition: String
// 这个是ViewController,不是View
let popupView: UIViewController
// 为了保持一致性,建议把类型放到变量的结尾,而不是开始,如submitButton
@IBOutlet weak var btnSubmit: UIButton!
@IBOutlet weak var buttonSubmit: UIButton!
// 在使用outlets 时,变量名内应包含类型名,或其他能表达类型含义的单词。
// 这里建议使用 firstNameLabel
@IBOutlet weak var firstName: UILabel!
}
2.7 数组的名称,推荐使用元素的复数命名。
// 推荐
var entities: [SPEntity] = []
// 不推荐
var entityList: [SPEntity] = []
三、语法规范
3.1 可选类型拆包取值时,使用if let 判断
if let data = result.data {
// code
}
3.2 多个可选类型拆包取值时,将多个if let 判断合并
if let name = person.name, let age = person.age {
// code
}
3.3 尽量不要使用 as! 或 try!(除非可以确定不会出现异常)
// 使用if let as?
if let name = person.name as? String {
// code
}
3.4 当对外接口不兼容时,使用@available(iOS x.0, *) 标明接口适配的起始系统版本号
@available(iOS 8.0, *)
func myFunction() {
// code
}
3.5 尽可能的多使用let,少使用var。
3.6 当拆包取值时,使用和被拆包取值变量相同的名称。
guard let myVariable = myVariable else {
return
}
3.7 在创建类常量的时候,使用 static 关键词修饰。
class MyTableViewCell: UITableViewCell {
static let reuseIdentifier = String(MyTableViewCell)
static let cellHeight: CGFloat = 80.0
}
3.8 推荐使用提前返回的策略,而不是 if 语句的嵌套。使用 guard 语句可以改善代码的可读性。
// 推荐
func eatDoughnut(atIndex index: Int) {
guard index >= 0 && index < doughnuts else {
// 如果 index 超出允许范围,提前返回。
return
}
let doughnut = doughnuts[index]
eat(doughnut)
}
// 不推荐
func eatDoughnuts(atIndex index: Int) {
if index >= 0 && index < donuts.count {
let doughnut = doughnuts[index]
eat(doughnut)
}
}
3.9 当需要判断变量是否是nil,但又不需要访问变量值的时候,推荐直接把它跟nil做比较。
// 推荐
if someOptional != nil {
// do something
}
// 不推荐
if let _ = someOptional {
// do something
}
四、注释
对于写代码,注释就是解释。除非在非常必要的时候进行适当的注释,否则只会增加阅读代码“噪声”。
尽量用注释说明why(为什么这里代码要这么写),而不是what(这里代码写的是什么)