团队Swift编码规范分享

本文始发于我的博文团队Swift编码规范分享,现转发至此。

目录

  • 命名
  • 格式
  • 准则
  • 文件
  • 场景
  • 参考

命名

【强制】命名清晰,保持一致性

反例:displayName(返回name还是展示name)

【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式

说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式也要避免采用。

正例:alibaba / taobao / youku / hangzhou 等国际通用的名称,可视同英文

反例:DaZhePromotion [打折]、getPingfenByName() [评分] / int 某变量 = 3

【强制】类、结构体、枚举、协议名使用大驼峰风格,常用缩写除外

正例:UserManager、UMSocialAdapter、TCPManager

【强制】函数、方法、变量、常量、参数使用小驼峰命名

【强制】协议名统一规范

作用为delegate,结尾添加Delegate;描述协议做的事,用名词描述;描述行为,用形容词,例如"able"或者"ing"等;如果两者不能满足,结尾添加Protocol。

正例:ScrollToTopable、UIDataSourceTranslating

【强制】缩略词使用完整大写,如果作为命名的开始部分,且首字母需要小写,则缩略词全小写

正例:

let userID = "123456"
let imageURL = "http://xxxxx"
class URLHandler {
  func urlConvert(urlString: String) {}
}

【强制】枚举项小写

正例:

enum CompassPoint {
  case north
  case south
  case east
  case west
}

【强制】命名先保证表达的意思准确,再考虑简短,不为了缩短书写而缩短书写

说明:比如有些属性适合定义成类属性;有些准确的需要定义成实例属性。

正例:UIDevice.current.isIphoneX

反例:UIDevice.isIphoneX

【强制】常量、变量命名若不能明显表明类型,则属性命名内要包括类型信息

正例:

// 变量名中可以表明类型,则命名中不需要包括类型信息
let animationDuration: NSTimeInterval
let userName: String  
// Controller命名 
// UIViewController、UITableViewController等简写成Controller
let popupController: UIViewController 
// UITabBarController和UINavigationController保留结构缩写
let flashSaleTabBarController: UITabBarController
// 命名中需要明确类型信息
let userImage: UIImage
let userImageURL: NSURL
let userImageURLString: String
// 当使用outlets时, 确保命名中标注类型
@IBOutlet weak var submitButton: UIButton!
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var nameLabel: UILabel!

【推荐】如果使用到了设计模式,建议在类名中体现出具体模式

说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计思想。

正例:class CommunityFollowTopicCellFactory、class TopicListCellBaseFactory

【强制】如果枚举类型的属性,其命名不能表明是枚举类型的,带上Enum后缀

正例:UserIdentityEnum、sectionType、playStatus、selectionStyle

【强制】声明属性时言简意赅,不带上类名

正例:

// 系统 UIDevice.current
// 而不是UIDevice.currentDevice
UserDefaults.standard // 而不是UserDefaults.standardDefaults
class RouteManager {
  static let shared = RouteManager() // 用shared,不用sharedManager 
}

【强制】区分使用default或shared

说明:default一般用于提供使用默认的参数配置的实例;shared一般用于单例。

【强制】如果省略外部参数名后会导致调用处含义模糊,则禁止省略

反例:

// 方法声明
class func action(_ pageName: String?, pageParam: String?, action: String, actionParam: [String: Any]?, isOutPoint: Bool = false) {} 
// 调用处 UserTracker.action("搜索", pageParam: searchType.rawValue, action: "语音输入", actionParam: ["keywords": result], isOutPoint: true)

【强制】函数命名中尽量不添加介词,如of、in、on、with等

正例:

// 原声明:UIFont.systemFontOfSize
open class func systemFont(ofSize fontSize: CGFloat) -> UIFont // 原声明:UIView.animateWithDuration
open class func animate(withDuration duration: TimeInterval, animations: @escaping () -> Swift.Void)

格式

【强制】如果语句的逻辑或长度较复杂,则使用变量保存再引用

反例:

AnyDataSourceService(dataSource: GoodsCommentResultDataSource(id: goodsId, offset: offset, imageOnly: imageOnly)).run(success: {
  [weak self] (data: GoodsCommentResult) in
})

正例:

let dataSource = GoodsCommentResultDataSource(id: goodsId, offset: offset, imageOnly: imageOnly)
let service = AnyDataSourceService(dataSource: dataSource)
service.run(success: { [weak self] (data: GoodsCommentResult) in
})

【强制】如果大括号内为空,则简洁地写成{}即可,不需要换行

【强制】枚举每一个case操作都换行,不跟在“:”后面

switch enum {
case a:
  methodA()
case b:
  methodB()
case c:
  methodC()
}

【推荐】如果switch内每一个case的操作大于5行,则封装成一个方法调用

【强制】变量类型,函数参数,遵循协议或继承父类,分号前不留空格

正例:

let str: String = "Test"
someFunction(someArgument: "Argument")
class ViewController: UIViewController {}
extension ViewController: UITableViewDelegate {}

【强制】逗号后面、运算符前后加空格

正例:

let array = [1, 2, 3, 4, 5]
let sum = 1 + 2
let isSuccess = sum == 3

【强制】左大括号不换行,左边保留空格

【强制】流程控制不使用小括号

正例:if x == y { }

【强制】使用枚举时用简写

正例:imageView.setImageWithURL(url, type: .person)

【强制】使用一些语句如 else,catch等紧随代码块的关键词的时候,确保代码块和关键词在同一行

正例:

do {
  try canThrowAnError()     // no error was thrown 
} catch {
  // an error was thrown 
} 
if name == "world" {
  print("hello, world")
} else {
  print("I'm sorry \(name), but I don't recognize you")
}

【强制】switch与case对齐

正例:

switch some value to consider {
case value 1:
  respond to value 1
case value 2, value 3:
  respond to value 2 or 3
default:
  otherwise, do something else 
}

【强制】不注释无用代码,直接删掉。若想保留代码以防以后用到,请使用git

【强制】文件末尾必须留且只留一行空白行

【强制】“//”注释符号后面要保留空格

【强制】求高度/字符串等较复杂时需按一下格式定义,清晰指明含义,方便他人维护

let factor1Top = 20
var factor1Height = 40
var factor2Height = 40
let bottomPadding = 30
if lineCount > 0 {
  let lineHeight = lineCount * 10
  factor1Height += lineHeight
}
if lineCount > 2 {
  let lineHeight = lineCount * 20
  factor2Height += lineHeight
}
let height = factor1Top + factor1Height + factor2Height + bottomPadding
return CGSize(width: width, height: height)

准则

【强制】若变量类型可以依靠推断得出,则声明时不要指明类型

正例:

let π = 3.14159

【强制】模型中需要指明数据类型

正例:

struct DiamondPackage {
  var id: Int = 0
  var count: Int = 0
  var price: Double = 0.0
  var desc: String?
  var descIconURL: NSURL?
  var iapProductId: String?
}

【强制】使用隐式拆包可选类型的场景只能是@IBOutlets和网络层Service(保证使用之前肯定有值非空时),其余情况禁止使用“!”隐式拆包

【强制】若需要判断当前值是否为nil,直接和nil比较

正例:if someOptional != nil {}

反例:if let _ = someOptional {}

【强制】使用属性时不用self.修饰

【强制】使用guard代替if提前返回

【强制】使用guard拆包多个可选值

正例:

guard let thingOne = thingOne, let thingTwo = thingTwo, let thingThree = thingThree else {     
  return 
}

【强制】严格设置访问权限open/public/internal/fileprivate/private

【强制】不使用的库不import进文件

说明:一般新建文件之后都会有默认代码:import Foundation,不需要则删除

文件

【强制】Controller文件结构

说明:Controller包含较多代码,需要适量划分,使得代码查找更方便

一般包含以下内容:

import
@IBOutlet
@IBAction
override
配置数据源(configSection和enum Row)
私有属性 开放属性 私有函数 开放函数
delegate/protocol

正例:

// import放最前面,先import系统库
import UIKit
import Alamofire
protocol ViewControllerDelegate: class {}
class ViewController: UIViewController {
  // 仅包含@IBOutlet、@IBAction、私有属性、公有属性、override方法
  // 顺序依次如下     
  // IBOutlet
  @IBOutlet var imageView: UIImageView!
  // 公有属性
  var showBottom: Bool = false       
  // 私有属性     
  private weak var delegate: ViewControllerDelegate?
  private var rows: [Row] = []
  override func viewDidLoad() {
    super.viewDidLoad()
    configVM()
    doSomething()
    // Do any additional setup after loading the view, typically from a nib.
  }
  // override按生命周期顺序
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
  }
  override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
  }
}  
// 每个extension内第一行空行
// @IBAction 
extension ViewController {

  @IBAction func clickButton() {}
}
// 类方法、开放的方法
extension ViewController {
  class func classMethod() {}
  func openMethod() {}
}
// 私有的方法 
private extension ViewController {
  func doSomething() {}
}
// 协议,每个协议分开写

extension ViewController: UITableViewDelegate {} 
extension ViewController: ScrollToTop {}
// 数据源配置相关放最后的extension
private extension ViewController {
  enum Row {
    case row1
    case row2
    case row3
  }
  func configVM() {
    rows = []
    rows.append(.row1)
  }
}

场景

  • 定义模型

【强制】唯一标识统一用id,不使用类似jobId写法

【强制】不参与运算的String不需要初始化,如name,desc等仅用于显示的字段

【强制】数组必须初始化,不使用optional写法

  • 使用CocoaPods

【强制】导入库需要指定某一个确定的版本号,禁止使用大于等于之类的指定

【强制】修改第三方库(禁止修改,除非特殊情况)需要新建一个Pod,并且在提交podfile修改的commit中注释原因

【强制】不轻易引入第三方库,除了网络库、JSON转模型库、路由库等

【强制】保持相同作用的库仅有一个

【推荐】团队开发的库尽量引入framework,不引入源码

参考

swift-style-guide

最详尽的 Swift 代码规范指南

17条 Swift开发规范 最佳实践

The Swift Programming Language (Swift 4)

-END-
欢迎到我的博客交流:https://zackzheng.info

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容