版本記錄
版本號 | 時間 |
---|---|
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)方法和屬性握联,有點類似于全局方法和屬性。但應盡量避免使用全局方法和屬性每瞒。有一些例外情況金闽,比如當使用runtime
的objc_getAssociatedObjec()
函數(shù)時,需要定義一個全局的key來作為參數(shù)剿骨。
可選類型
當使用?
來定義可選類型時代芜,表明它可以接受為nil
的值;
當使用!
來定義可選類型時浓利,表明它可以接受為nil
的值挤庇,但必須保證在使用它時,值不為nil
贷掖;
使用可選綁定來一次性解包單個或多個可選類型值
類型推導
對于局部變量嫡秕,盡量使用類型推導來讓代碼更緊湊。而對于成員變量來說苹威,應盡量不要使用類型推導來讓類的定義更清晰昆咽。
語法糖
利用語法糖,使用更簡短的聲明方式
內(nèi)存管理
可以通過使用weak
和unowned
來避免循環(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