Swift开发规范

一. 命名规范:

  • 大驼峰原则: 每个单词首字母大写。
  • class、struct、enum、protocol等命名。例:
class LoginName { } 
enum SexType { }
  • 小驼峰原则: 第一个单词首字母小写,其余单词首字母大写。
    • 方法名、参数名、成员变量、局部变量、枚举成员等声明。例:
var loginName: String
func getMessageInfo() 
  • _ 原则: 不同部分采用 _ 分割
    • 图片,json,color等资源命名。例
home_preview_invisible
button_bg_normal
  • 语义清晰,简洁: 所有命名和规范都应尽可能的与苹果API保持一致
  • 不要使用不规范的缩写:力求语义表达完整清楚,能直观的表达意图,不怕名称长
正例:class RoundAnimatingButton: UIButton {}
反例:class CustomButton: UIButton {}  / AbstractClass 缩写成 AbsClass

二. 基本标准:

  • 修饰符:
    • 用访问限制修饰符控制类、方法等的访问限制,遵循开闭原则; 说明:如确定某方法或变量不应该被外部调用,就使用private进行修饰,编译程序阻止外部不合适的调用。
    • extension 上不用加任何修饰符,修饰符加在 extension 内的变量或方法上;目的是当修改extension中某个方法的访问限制时,不需去考虑外部的extension访问限制,降低影响面
正例:
    extension UIView {
        public func removeAllSubView() {}
    }
反例:
    public extension UIView {
        func removeAllSubView() {}
    }
  • 修饰符顺序按照 注解、访问限制、static、final 顺序; 说明:注解是指起始于 @的关键字,如@discardableResult、@objc等;访问限制是指public、private等;
正例:
    class ApplicationServiceManager {
        public static let shared =  ApplicationServiceManager()
        private init {}
    }
  • 代码功能分区: 例:
// MARK: - Life Cycle
    
    // MARK: - UI
    
    /// 设置UI
    private func setupUI() {
        
    }
    
    // MARK: - Event
        
    // MARK: - Public method
    
    // MARK: - Private method
    
    // MARK: - 系统delegate
    
    // MARK: - 自定义delegate
    
    // MARK: - 第三方delegate
    
    // MARK: - Api
  • TODO: 临时处理方案或未实现的加TODO标记
// TODO: - 待完成功能
  • warning: 紧急异常功能加warning,添加到警告⚠️中
#warning("异常功能")
  • 布尔类型属性使用 is 作为属性名前缀,返回值为布尔型类型的方法名使用 is 作为方法名作为前缀;
  • 尽量不使用 !强制解包,优先使用 guard 解包,避免形成判断嵌套;
  • 在闭包中使用 self 时使用捕获列表[weak self]避免循环引用,闭包开始判断 self 的有效性;
正例:   
  let timer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { [weak self] _ in        
      guard let self = self else { return }     
      self.timerHandle()    
 }
  • 使用委托和协议时,避免循环引用,定义属性的时候使用 weak 修饰;

三. 格式规范:

  • 类、函数左大括号不另起一行,与名称之间留有空格;
  • 代码中的空格出现地点
    • 注释符号与注释内容之间有空格;
    • 类继承,参数名和类型之间等,冒号前面不加空格,但后面跟空格;
    • 任何运算符前后有空格;
    • 表示返回值的 -> 两边;
    • 参数列表、数组、元祖、字典里的逗号后面有一个空格;
  • 禁止使用无用分号;
  • 方法之间空一行;
  • 重载的声明放在一起,按照参数的多少从少到多向下排列;
  • 每一行只声明一个常、变量;
  • 如果大括号内为空,直接简写为{},括号之间不需换行;
  • if 后面的 else\else if, 跟着上一个 if\else if 的右括号;
  • switch 中,case 跟 switch 左对齐;
  • 解包时推荐使用原有名字,前提是解包后的名字与解包前的名字在作用域上不会形成冲突;
  • 实现每个协议时,在单独的 extension 里来实现
/**
 涉及规约
 1、类左大括号不另起一行;
 2、类继承后跟空格;
 */

/// 格式规约示例
class FormatSample: NSObject {
    /**
     涉及规约
     1、注释符号与注释内容之前有空格;
     2、每一行只声明一个变量;
     3、不使用分号;
     4、注释另起一行,不放在行尾;
     5、数组、元祖、字典里的逗号后面有一个空格;
     */

    private var resultCode = ""
    private var resultArr = ["one", "two"]
    private var resultDic = ["key": "name", "value": "张三"]
    private var resultTuple = (key: "name", value: "张三")
}

/**
 涉及规约
 1、方法之间空一行;
 2、重载的声明放在一起,按照按照参数的多少从少到多排序;
 3、返回值 -> 两遍增加空格;
 4、参数名与类型之间空格;
 5、如果大括号内为空,则直接简写为{},括号内不换行;
 6、if 后面的 else\else if, 跟着上一个 if\else if 的右括号;
 7、解包时推荐使用原有名字;
 */
extension FormatSample {
    private func logInfo(message: String) {
        logInfo(message: message, type: nil)
    }

    private func logInfo(message: String, type: String?) {
        if let type = type {
            print("\(type): \(message)")
        } else {
            print(message)
        }
    }

    private func canLog() -> Bool {
        #if DEBUG
            return true
        #else
            return false
        #endif
    }

    /**
     涉及规约
     1、switch 中, case 跟 switch 左对齐;
    */
    private func showSwitchStandardFormat() {
      let count = 10
      switch count {
      case 1:
        print(1)
      // 如case包含所有情况,可不加default,如遍历枚举类型时
      default:
        break
      }
    }
}
  • Swift 会被结构体按照自身的成员自动生成一个非 public 的初始化方法,如果这个初始化方法刚好适合,不要自己再声明;
/// 会自动生成 init(name: String) 这样的构造函数,如果符合使用,不要再手动添加该构造函数 
struct LoginInfo {  
     var name: String
 }
  • 类及结构体初始化方法不要直接调用.init,直接直接省略,使用 ();
正例:
  let loginView = UIView()
反例:
  let loginView = UIView.init()
  • 如果只有一个 get 的计算属性,忽略 get;
正例:
    var info: String {
      return ""
    }
反例:
    var info: String {
      get {
        return ""
      }
    }
  • 数据定义时,简单类型尽量使用字面量形式进行自动推断,如果上下文不足以推断字面量类型或者类型比较复杂时,需要声明赋值类型;
正例:var info = ""
反例:var info: String = ""
  • 省略默认的访问权限(internal);
正例:var info = ""
反例:internal var info = ""
  • 使用枚举属性时使用自动推断,进行缩写;
enum Sex {
  case male
  case female
}
正例:let sex: Sex = .male
反例:let sex: Sex = Sex.male
  • switch-case 里不用显式添加 break;
let count = 10
switch count {
case 1:
  print(1)
  // 此处不用显式添加break,Swift中每个case都会默认break。
}
  • 当方法无返回值时,不需添加 void;
正例:func getMessageInfo() {}
反例:func getMessageInfo() -> Void {}
  • 无用的代码及时删除; 说明:可能有些代码可能后续会用到,所以采取了注释的方式。但是这种方式很容易演变成代码会一直放在那,永远不会删掉。即使觉得后续会用到,也请及时删除掉,通过Git 版本控制回退
  • 过滤,转换等,优先使用 filter, map 等高阶函数简化代码,并尽量使用最简写;
  • 类似注解的修饰词单独占一行,如@objc,@discardableResult 等

四. 注释规范

  • ///:文档(API)注释使用单行注释,建议使用快捷键: Option + command + /⌥ ⌘ / ,不使用多行注释,即/** */。 多行注释用于对某一代码段、设计或者复杂业务进行描述;
  • //: 业务逻辑说明等。快捷键: command + / ⌘ /
  • 对于公开的类、方法以及属性等必须加上文档(API)注释///,方法需要加上对应的Parameter(s)、Returns、Throws 等标签,自动生成文档模板;
  • 将注释放在代码上一行,而不是放在代码后; 说明:放在代码后有两个弊端,一是当代码稍微长一点后,注释可能需要横向滚动后才能看全;另一个弊端是,当代码修改,极易将注释删除,或者由于后面有注释,前面的代码修改起来有些许不方便。
  • 在代码中灵活的使用一些地标注释,如MARK、FIXME、TODO,当同一文件中存在多种类型定义或者多种逻辑时,可以使用Mark进行分组注释,方便通过Xcode顶部面包屑进行切换;
// MARK: - View子视图操作相关

extension UIView {
    /// 同时添加多个视图
    /// - Parameter subviews: 子View可变参数
    public func addSubviews(_ subviews: UIView...) {
        subviews.forEach(addSubview)
    }

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

推荐阅读更多精彩内容