最近在閱讀swift進(jìn)階這本書,其中的風(fēng)格指南,我每次打開書要讀的時(shí)候,我都會(huì)先看一遍這個(gè)指南,因?yàn)橛X得真的很好.這里貼在簡(jiǎn)書上,和大家分享一下,有些指南后面我會(huì)加上示例代碼:
對(duì)于命名媒咳,在使用時(shí)能清晰表意是最重要。因?yàn)?API 被使用的次數(shù)要遠(yuǎn)遠(yuǎn)多于被聲明的次數(shù)翎朱,所以我們應(yīng)當(dāng)從使用者的角度來考慮它們的名字婴梧。盡快熟悉 Swift API 設(shè)計(jì)準(zhǔn)則枪汪,并且在你自己的代碼中堅(jiān)持使用這些準(zhǔn)則
// 盡量讓命名語義化,而且swift不需要前綴,因?yàn)橛忻臻g
// GOOD
extension List {
public mutating func remove(at position: Index) -> Element
}
employees.remove(at: x)
// 反例
// BAD
extension List {
public mutating func removeAt(position: Index) -> Element
}
employees.remove(x)
簡(jiǎn)潔經(jīng)常有助于代碼清晰藕筋,但是簡(jiǎn)潔本身不應(yīng)該獨(dú)自成為我們編碼的目標(biāo)
務(wù)必為函數(shù)添加文檔注釋 — 特別是泛型函數(shù)
// 官方的API里面map函數(shù)的注釋文檔,記住如果你想讓你的注釋
// 像官方文檔一樣按住option單擊左鍵就能看到,請(qǐng)使用 ///
// GOOD
/// Returns an array containing the results of mapping the given closure
/// over the sequence's elements.
///
/// In this example, `map` is used first to convert the names in the array
/// to lowercase strings and then to count their characters.
///
/// let cast = ["Vivien", "Marlon", "Kim", "Karl"]
/// let lowercaseNames = cast.map { $0.lowercaseString }
/// // 'lowercaseNames' == ["vivien", "marlon", "kim", "karl"]
/// let letterCounts = cast.map { $0.characters.count }
/// // 'letterCounts' == [6, 6, 3, 4]
///
/// - Parameter transform: A mapping closure. `transform` accepts an
/// element of this sequence as its parameter and returns a transformed
/// value of the same or of a different type.
/// - Returns: An array containing the transformed elements of this
/// sequence.
public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
// 反例,下面這種注釋是很多人會(huì)范的錯(cuò)
// 更值得提示的是,請(qǐng)多使用MARK來給業(yè)務(wù)邏輯分段
// BAD
// map函數(shù)
public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
類型使用大寫字母開頭,函數(shù)竭鞍、變量和枚舉成員使用小寫字母開頭匣椰,兩者都使用駝峰式命名法
// Class使用大寫字母開頭就不用多說了.
// 這里需要注意的是,在swift中,enum使用小寫字母開頭
// 這個(gè)跟OC有很大區(qū)別
// GOOD
enum RequestPath {
case index
case discover
}
// BAD
enum RequestPath {
case Index
case Discover
}
使用類型推斷裆熙。省略掉顯而易見的類型會(huì)有助于提高可讀性
// 有人覺得使用類型推斷會(huì)使得執(zhí)行效率下降
// 筆者可以負(fù)責(zé)任的告訴你,完全不會(huì),因?yàn)轭愋屯茢嗍蔷幾g器完成的
// GOOD
let str: String = "ABC"
// BAD
let str = "ABC"
優(yōu)先選擇結(jié)構(gòu)體,只在確實(shí)需要使用到類特有的特性或者是引用語義時(shí)才使用類
在swift
中struct
是值類型(value type),而類是引用類型(reference type),值類型在傳遞的過程中是會(huì)被拷貝的,所以無副作用
除非你的設(shè)計(jì)就是希望某個(gè)類被繼承使用,否則都應(yīng)該將它們標(biāo)記為 final
在swift
中被標(biāo)記final
關(guān)鍵字的類,都是不允許繼承的,如果是方法被標(biāo)記了final
,則是不允許重寫
除非一個(gè)閉包后面立即跟隨有左括號(hào)入录,否則都應(yīng)該使用尾隨閉包 (trailing closure) 的語法
// GOOD
UIView.animate(withDuration: 0.3) {
}
// BAD
UIView.animate(withDuration: 0.3, animations: {
})
使用 guard 來提早退出方法
// guard可以使得條件不成立的時(shí)候執(zhí)行else里面的代碼
// 如果成立則繼續(xù)執(zhí)行下面的代碼
// GOOD
guard webView.isKind(of: WKWebView.self) else {
return
}
// 執(zhí)行業(yè)務(wù)代碼
// BAD
if webView.isKind(of: WKWebView.self) {
// 執(zhí)行業(yè)務(wù)代碼
} else {
}
避免對(duì)可選值進(jìn)行強(qiáng)制解包和隱式強(qiáng)制解包耘分。它們偶爾有用惕味,但是經(jīng)常需要使用它們的話往往意味著有其他不妥的地方
這里沒啥可說的,誰用誰知道,結(jié)果就是crash
,所以建議使用optional chains
self.textContainer?.textLabel?.setNeedsDisplay() // 保平安
不要寫重復(fù)的代碼霜第。如果你發(fā)現(xiàn)你寫了好幾次類似的代碼片段的話丐怯,試著將它們提取到一個(gè)函數(shù)里,并且考慮將這個(gè)函數(shù)轉(zhuǎn)化為協(xié)議擴(kuò)展的可能性
試著去使用 map 和 reduce蚀同,但這不是強(qiáng)制的缅刽。當(dāng)合適的時(shí)候,使用 for 循環(huán)也無可厚非蠢络。高階函數(shù)的意義是讓代碼可讀性更高衰猛。但是如果使用 reduce 的場(chǎng)景難以理解的話,強(qiáng)行使用往往事與愿違刹孔,這種時(shí)候簡(jiǎn)單的 for 循環(huán)可能會(huì)更清晰
// map
numbers.map { $0 * 2 }
// for
for i in numbers {
i * 2
}
試著去使用不可變值:除非你需要改變某個(gè)值啡省,否則都應(yīng)該使用 let 來聲明變量。不過如果能讓代碼更加清晰高效的話髓霞,也可以選擇使用可變的版本卦睹。用函數(shù)將可變的部分封裝起來,可以把它帶來的副作用進(jìn)行隔離
除非你確實(shí)需要方库,否則不要使用 self.结序。在閉包表達(dá)式中,使用 self 是一個(gè)清晰的信號(hào)薪捍,表明閉包將會(huì)捕獲 self
// 有些開發(fā)者是從Objective - C轉(zhuǎn)過來的,非常喜歡使用self
// 其實(shí)在swift中完全沒有必要
// 但是在閉包中使用self是規(guī)定
anotherNum.map { num in
self.numbers.append(num)
}
盡可能地對(duì)現(xiàn)有的類型和協(xié)議進(jìn)行擴(kuò)展笼痹,而不是寫一些全局函數(shù)配喳。這有助于提高可讀性酪穿,讓別人更容易發(fā)現(xiàn)你的代碼
// 多用extension
// 在開發(fā)中經(jīng)常遇到這樣的問題
// 如果把代理方法直接放在當(dāng)前類里面會(huì)使得代碼臃腫不堪
// 通過extension可以使得兩者分離開
// 如果你愿意,你甚至可以寫在兩個(gè)文件里面都沒有關(guān)系
// 比如代理方法,完全可以通過extension的方式使用
// 這樣是得代碼的調(diào)理性更加清晰
extension WebViewController: WKUIDelegate, WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.title = webView.title!
}
}
生命不息,折騰不止...
I'm not a real coder, but i love it so much!