Swift 代碼規(guī)范

版本記錄

版本號 時間
V1.0 2018.12.4

前言

Swift是編寫軟件的絕佳方式,無論是用于手機,臺式機柏锄,服務器還是其他任何運行代碼的軟件赠涮。它是一種安全,快速,交互式的編程語言,它將現(xiàn)代語言思維的最佳結(jié)合與來自更廣泛的Apple工程文化的智慧和來自開源社區(qū)的各種貢獻相結(jié)合。編譯器針??對性能進行了優(yōu)化亩冬,語言針對開發(fā)進行了優(yōu)化,而不會對其進行任何影響硼身。

Swift對新程序員很友好硅急。它是一種工業(yè)級編程語言枢冤,與腳本語言一樣富有表現(xiàn)力和樂趣。在playground上編寫Swift代碼可以讓您試驗代碼并立即查看結(jié)果铜秆,而無需構(gòu)建和運行應用程序的開銷淹真。

正文

正確性

力爭讓代碼沒有編輯警告(warning)。這個規(guī)則下衍生出了許多決定连茧,如:使用#selector方式核蘸,而不是直接使用字符串。
注意:由于iOS系統(tǒng)版本升級啸驯,同時App支持版本的問題客扎,合理選擇正確的未失效方法,可消除部分編譯警告罚斗。

命名

描述性和一致性的命名會讓代碼更加的易讀徙鱼、易懂。命名請遵循一下規(guī)則:

  • 追求調(diào)用方的清晰性
  • 優(yōu)先使用更清晰的命名针姿,而不是更簡潔的命名
  • 使用駝峰樣式
  • 類型袱吆、協(xié)議名首字符大寫,其他的都首字母小寫
  • 包含所有需要的單詞距淫,省略不必要的
  • 使用基于角色的命名绞绒,而不是基于類型的
  • 工廠方法使用make開頭
  • 對方法的命名
  • 不要使用生僻的單詞
  • 通常不要用縮寫
  • 選用好的參數(shù)名來起到描述的作用
類前綴

Swift中的類型自動使?了其所在的模塊作為命名空間,所以不必給類型加
前綴榕暇。如果來?不同模塊的類型名字沖突蓬衡,可以顯示的使?模塊名作為調(diào)?前綴來避免沖突。

建議

import SomeModule
import OtherModule
let someUsefulClass = SomeModule.UsefulClass()
let otherUsefulClass = OtherModule.UsefulClass()
代理

當定義一個代理?法時彤枢,第一個匿名參數(shù)應該是代理的源對象狰晚。( UIKit 中有許多這樣的的例子)

建議

func numberOfSections(in tableView: UITableView) -> Int
使?可類型推導的上下?文

利用好編譯器?的類型推斷特性,來寫出簡短缴啡、清晰的代碼壁晒。

建議

self.collectionView.backgroundColor = .white
泛型

泛型參數(shù)應當使?具有描述性的駝峰樣式來命名。當泛型參數(shù)不具有
明確的關(guān)系或??時盟猖,可使??個?寫的字母表示即可讨衣。如: T 换棚, U 式镐, V

使?的語?

應使?用美式英語的拼寫?方式以匹配Apple的API,應盡量保持命名的可讀性固蚤,不應該?多含義且有相反或者混淆意思的單詞娘汞。

建議

let color = "white"

不建議

let colour = "white"

代碼組織

盡可能的使?擴展(extensions)來解耦你的代碼,將代碼劃分到不同的擴展模塊中夕玩,每個擴展盡量使用// MARK: -開頭你弦,用以來更好的區(qū)分擴展惊豺。

協(xié)議的遵守

具體來講,當讓一個Model遵守某個協(xié)議時禽作,推薦添加一個獨立的Model擴展(extensions)來遵守該協(xié)議尸昧。這樣使得相關(guān)的協(xié)議?法能組織在一起。

對于 UIKit 的視圖控制器(view controllers)旷偿,可以考慮將?生命周期(LifeCycle)相關(guān)烹俗、?定義訪問器( custom accessors )、 IBAction 獨?不同的到類擴展中萍程。

建議

// MARK: - UITableViewDelegate
extension XXViewController: UITableViewDataSource, UITableViewDelegate
?用的代碼

?用的代碼包括Xcode產(chǎn)?生的模板代碼幢妄、占位的注釋等、?法的默認實現(xiàn)僅僅是調(diào)用 super 等茫负,這些都應當移除掉蕉鸳。

建議

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.dataList.count
}

不建議

// 該方法什么都沒干,存在反而會增加小伙伴的閱讀量
override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
}
減小引入

保存最小的引入(imports)忍法。例如, 當只使用Foundation時潮尝,不要引?入UIKit

空格
  • 代碼折行使用4個空格
  • 方法的大括號和其他大括號(if/else/switch/while)饿序,其左括號必須要和語句在同一個行衍锚,并且右括號要換行;
    建議
if XXX == 1 {
    // do something
} else {
    // do something else
}
  • 變量類型和冒號(:)之間保留一個空格嗤堰;
    建議
let cellHeight: CGFloat = 73.5
  • 返回值標記(->)兩側(cè)各保留一個空格戴质;
    建議
func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect
  • 各個方法之間必須有一個空格,這使得代碼視覺上更清晰踢匣;
  • 方法的實現(xiàn)中告匠,應當適當?shù)奶砑涌招衼韯澐止δ堋_^多的空行意味著應該拆分這些功能到不同的方法中离唬,通過這樣來避免一個巨大的方法后专;
  • 通常冒號(:)的左邊應當沒有空格,而在右邊有一個空格输莺。當然這個是有例外的戚哎,如:三目運算符、空字段嫂用、無參數(shù)方法等型凳;

建議

var delegate: UICollectionViewDelegate?
注釋
  • 給方法或者屬性添加注釋,可以使用option + command + /來讓Xcode自動生成,也可以使用MARK: -等;
    option + command + /效果如下
/// <#Description#>
    ///
    /// - Parameters:
    ///   - pageNo: <#pageNo description#>
    ///   - lon: <#lon description#>
    ///   - lat: <#lat description#>
    ///   - state: <#state description#>
    ///   - responseComplete: <#responseComplete description#>
    func requstNetData(_ pageNo: Int,
                       _ lon: Double,
                       _ lat: Double,
                       _ state: Int,
                       _ responseComplete: HttpComplete) {
        
    }
  • 給關(guān)鍵邏輯添加一些局部注釋嘱函,單行注釋請用//;
  • 注釋要保持最新狀態(tài);

類與結(jié)構(gòu)體

結(jié)構(gòu)體(struct)是值類型甘畅,當事物不具有唯一性時,使用結(jié)構(gòu)體。
類是引用類型疏唾,當事物具有唯一性或者有明確的生命周期時蓄氧,使用類。
以下是一個類的定義

class Circle: Shape {
    var x: Int
    var y: Int
    var radius: Double
    var diameter: Double {
        get {
            return radius * 2
        }
        set {
            radius = newValue / 2
        }
    }
    init(x: Int, y: Int, radius: Double) {
        self.x = x
        self.y = y
        self.radius = radius
    }
    convenience init(x: Int, y: Int, diameter: Double) {
        self.init(x: x, y: y, radius: diameter / 2)
    }
    override func area() -> Double {
        return Double.pi * radius * radius
    }
}
extension Circle: CustomStringConvertible {
    var description: String {
        return "center = \(_centerString) area = \(area())"
    }
    private var _centerString: String {
        return "(\(x),\(y))"
    }
 }
使用self

在Swift中槐脏,可以通過利用好編譯器的類型推斷特性省略self來訪問一個獨享的屬性或者方法喉童。但是為了消除使用的歧義,建議使用self來訪問顿天。

計算屬性

為了簡潔性泄朴,如果?個計算屬性是只讀(read-only)的,那么應省略 get { ... } 語句露氮。get { ... }語句只在計算屬性是讀寫( read-write )時祖灰,才要求使?。

建議

var area: Double {
    return width * height
}
使用final標記

出于某些原因畔规,你可能不希望一個類被繼承局扶,這時你可以將其標記為final來表示它不不能被繼承。
例如:一個單例叁扫,可能就不希望被繼承三妈。

函數(shù)聲明

  • 將簡短的函數(shù)聲明保留在一行中,包括左括號;

建議

func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?
  • 無返回值的函數(shù)可以省略(-> Void)返回值;

建議

func register(_ nib: UINib?, forCellWithReuseIdentifier identifier: String)
  • 參數(shù)較多的函數(shù)可以像Objective-C中一樣進行折行處理;

建議

func foo(arg1: Int,
         arg2: Double,
         arg3: String,
         arg4: [Bool],
         arg5: () -> Void) {
    /* code goes here */
}
閉包表達式

當參數(shù)列表末尾只有一個閉包參數(shù)時莫绣,才應該使用尾隨閉包語法畴蒲。

對于使?閉包的鏈式調(diào)?,應當讓代碼更清晰对室、更易讀模燥。可以借助空格(spacing)掩宜、換?(line breaks)和匿名參數(shù)(anonymous arguments)等?法來讓代碼更清晰蔫骂、更易讀,但這都依賴于你的選擇牺汤。

類型

應盡量使用Swift的原生類型辽旋,當然Swift提供了對Objective-C類型的橋接方法,你可以使用Objective-C的所有方法檐迟。

建議

let width = 120.0                                    // Double
let widthString = (width as NSNumber).stringValue
常量

常量使用關(guān)鍵字let定義,變量使用關(guān)鍵字var定義补胚。除非值可變,否則都應該用關(guān)鍵字let定義追迟。
在一個類型的內(nèi)容溶其,通過關(guān)鍵字static let來定義靜態(tài)常量,這樣可以更好的組織這些靜態(tài)變量怔匣。

建議

enum Math {
    static let e = 2.718281828459045235360287
    static let pi = 3.14159265358979323846264
}

類內(nèi)部的靜態(tài)方法和屬性握联,有點類似于全局方法和屬性。但應盡量避免使用全局方法和屬性每瞒。有一些例外情況金闽,比如當使用runtimeobjc_getAssociatedObjec()函數(shù)時,需要定義一個全局的key來作為參數(shù)剿骨。

可選類型

當使用?來定義可選類型時代芜,表明它可以接受為nil的值;
當使用!來定義可選類型時浓利,表明它可以接受為nil的值挤庇,但必須保證在使用它時,值不為nil贷掖;
使用可選綁定來一次性解包單個或多個可選類型值

類型推導

對于局部變量嫡秕,盡量使用類型推導來讓代碼更緊湊。而對于成員變量來說苹威,應盡量不要使用類型推導來讓類的定義更清晰昆咽。

語法糖

利用語法糖,使用更簡短的聲明方式

內(nèi)存管理

可以通過使用weakunowned來避免循環(huán)引用牙甫,但也可以直接使用值類型(struct,enum)來避免循環(huán)引用掷酗。

可以通過guard let的形式來產(chǎn)生strongSelf

建議

guard let sSelf = self else { return }

訪問控制

一般來說,被標記為private窟哺、fileprivate的屬性或方法都應以下劃線(_)開頭泻轰。例外情況是,當標記被修飾為private(set)且轨、fileprivate(set)時浮声,不需要下劃線(_)開頭,因為他們都是可訪問的屬性旋奢,只是他們都是只讀屬性而已阿蝶。

建議

private var _isEnabled: Bool
fileprivate var _isClosed: Bool
private func _foo() {
    // code goes here
}
fileprivate func _bar() {
    // code goes here
}
private(set) var isEnabled: Bool
fileprivate(set) var isClosed: Bool

一般將訪問控制標記放在聲明的最前面,但例外情況中黄绩,當有屬性標記@IBAction羡洁、@IBOutlet@discardableResult爽丹、@objc時筑煮,需要將屬性標記放在最前面。

建議

@IBOutlet private var _titleLab: UILabel!

控制流

優(yōu)先使用for-in的方式而不是while

建議

for (index, person) in attendeeList.enumerated() {
    print("\(person) is at position #\(index)")
}

使用Guard語句

通過使用guard來避免使用if時代碼塊的深度嵌套問題

建議

 
func check(phone: String?, name: String?, age: Int) -> Bool { 
      // 把對phone粤蝎、name真仲、age的判斷放到?一個guard?里里,更更簡潔
      guard
            let ph = phone, ph.count > 0,
            let nm = name, nm.count > 0,
            age > 0 else {
            return false
            }
            return true 
}

分號

在Swift中不要求必須加分號初澎,一般情況下你不需要使用分號秸应。只有當你希望將多行代碼寫在一行時虑凛,才需要加分號來斷句。

圓括號

一般情況下软啼,在類型if條件桑谍、for循環(huán)等控制語句中不需要加圓空號。只有當你在進行數(shù)學運算時祸挪,希望代碼可讀性更高時才需要適當?shù)奶砑訄A括號锣披。
建議

let result = ((x * y) + 2) / h
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市贿条,隨后出現(xiàn)的幾起案子雹仿,更是在濱河造成了極大的恐慌,老刑警劉巖整以,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胧辽,死亡現(xiàn)場離奇詭異,居然都是意外死亡公黑,警方通過查閱死者的電腦和手機票顾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帆调,“玉大人奠骄,你說我怎么就攤上這事》” “怎么了含鳞?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長芹务。 經(jīng)常有香客問我蝉绷,道長,這世上最難降的妖魔是什么枣抱? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任熔吗,我火速辦了婚禮,結(jié)果婚禮上佳晶,老公的妹妹穿的比我還像新娘桅狠。我一直安慰自己,他們只是感情好轿秧,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布中跌。 她就那樣靜靜地躺著,像睡著了一般菇篡。 火紅的嫁衣襯著肌膚如雪漩符。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天驱还,我揣著相機與錄音嗜暴,去河邊找鬼凸克。 笑死,一個胖子當著我的面吹牛闷沥,可吹牛的內(nèi)容都是我干的萎战。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼狐赡,長吁一口氣:“原來是場噩夢啊……” “哼撞鹉!你這毒婦竟也來了疟丙?” 一聲冷哼從身側(cè)響起颖侄,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎享郊,沒想到半個月后览祖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡炊琉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年展蒂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苔咪。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡锰悼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出团赏,到底是詐尸還是另有隱情箕般,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布舔清,位于F島的核電站丝里,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏体谒。R本人自食惡果不足惜杯聚,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抒痒。 院中可真熱鬧幌绍,春花似錦、人聲如沸故响。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽被去。三九已至主儡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惨缆,已是汗流浹背糜值。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工丰捷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人寂汇。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓病往,卻偏偏與公主長得像,于是被迫代替她去往敵國和親骄瓣。 傳聞我的和親對象是個殘疾皇子停巷,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 1. 代碼格式 1.1 使用四個空格進行縮進。 1.2 每行最多160個字符榕栏,這樣可以避免一行過長畔勤。 (Xcode...
    余一波_Bobby閱讀 5,921評論 1 3
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學習記錄文檔,今天18年5月份再次想寫文章扒磁,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 2,771評論 2 9
  • 1.編碼格式 1.1 使用四個空格進行縮進(在 Xcode > Preferences > Text Editin...
    Chevee閱讀 619評論 0 1
  • 一. 宗旨 尊重蘋果原生的命名和書寫規(guī)范 能清晰表達含義 簡潔而不省略 減少不必要的注釋 二. 編碼規(guī)范 1. 運...
    Mccc_閱讀 2,276評論 2 12
  • 團隊的Swift代碼規(guī)范庆揪,參考Swift Style Guide和Swift 4.0 編碼規(guī)范,并根據(jù)團隊實際需要...
    猿類素敵閱讀 742評論 0 2