protocol TableViewSectionProvider { func rowHeight(at row: Int) -> CGFloat var numberOfRows: Int { get } /* ... */ }
able
或 ing 。 (如 Equatable、 ProgressReporting)protocol Loggable { func logCurrentState() /* ... */ } protocol Equatable { func ==(lhs: Self, rhs: Self) -> bool { /* ... */ } }
Protocol
後綴protocol InputTextViewProtocol { func sendTrackingEvent() func inputText() -> String /* ... */ }
推薦:html
class MyViewController: UIViewController { // class stuff here } // MARK: - UITableViewDataSource extension MyViewController: UITableViewDataSource { // table view data source methods } // MARK: - UIScrollViewDelegate extension MyViewController: UIScrollViewDelegate { // scroll view delegate methods }
不推薦:git
class MyViewController: UIViewController, UITableViewDataSource, UIScrollViewDelegate { // all methods }
var isString: Bool = true
public enum UITableViewRowAnimation : Int { case fade case right // slide in from right (or out to right) case left case top case bottom case none // available in iOS 3.0 case middle // available in iOS 3.2. attempts to keep cell centered in the space it will/did occupy case automatic // available in iOS 5.0. chooses an appropriate animation style for you }
推薦 HomeViewController Bundle 不推薦 NEHomeViewController NSBundle
推薦 let viewFrame = view.frame let textField = ... let table = ... let controller = ... let button = ... let label =... 不推薦 let r = view.frame let tf = ... let tb = ... let vc =... let btn = ... let lbl =...
推薦 class TestClass: class { // UIKit的子類,後綴最好加上類型信息 let coverImageView: UIImageView @IBOutlet weak var usernameTextField: UITextField! // 做爲屬性名的firstName,明顯是字符串類型,因此不用在命名裏不用包含String let firstName: String // UIViewContrller以ViewController結尾 let fromViewController: UIViewController } 不推薦 class TestClass: class { // image不是UIImageView類型 let coverImage: UIImageView // or cover不能代表其是UIImageView類型 var cover: UIImageView // String後綴多餘 let firstNameString: String // UIViewContrller不要縮寫 let fromVC: UIViewController }
func min(_ number1: int, _ number2: int) { /* ... */ } min(1, 2)
extension UInt32 { /// 安全值類型轉換,16位轉32位,可省略參數標籤 init(_ value: Int16) /// 非安全類型轉換,64位轉32位,不可省略參數標籤 /// 截斷顯示 init(truncating source: UInt64) /// 非安全類型轉換,64位轉32位,不可省略參數標籤 /// 顯示最接近的近似值 init(saturating valueToApproximate: UInt64) }
推薦 // 添加介詞標籤havingLength func removeBoxes(havingLength length: int) { /* ... */ } x.removeBoxes(havingLength: 12)
推薦 // 介詞To提早 a.moveTo(x: b, y: c) // 介詞From提早 a.fadeFrom(red: b, green: c, blue: d) 不推薦 a.move(toX: b, y: c) a.fade(fromRed: b, green: c, blue: d)
// 參數構成語句一部分,省略第一個參數標籤 x.addSubview(y) // 參數不構成語句一部分,不省略第一個參數標籤 view.dismiss(animated: false)
推薦 func remove(_ member: Element) -> Element? 不推薦 func removeElement(_ member: Element) -> Element?
推薦 let urlRouterString = "https://xxxxx" let htmlString = "xxxx" class HTMLModel { /* ... */ } struct URLRouter { /* ... */ } 不推薦 let uRLRouterString = "https://xxxxx" let hTMLString = "xxxx" class HtmlModel { /* ... */ } struct UrlRouter { /* ... */ }
// 推薦 class ConnectionTableViewCell: UITableViewCell { let personImageView: UIImageView let animationDuration: NSTimeInterval // 做爲屬性名的firstName,很明顯是字符串類型,因此不用在命名裏不用包含String let firstName: String // 雖然不推薦, 這裏用 Controller 代替 ViewController 也能夠。 let popupController: UIViewController let popupViewController: UIViewController // 若是須要使用UIViewController的子類,如TableViewController, CollectionViewController, SplitViewController, 等,須要在命名裏標名類型。 let popupTableViewController: UITableViewController // 當使用outlets時, 確保命名中標註類型。 @IBOutlet weak var submitButton: UIButton! @IBOutlet weak var emailTextField: UITextField! @IBOutlet weak var nameLabel: UILabel! } // 不推薦 class ConnectionTableViewCell: UITableViewCell { // 這個不是 UIImage, 不該該以Image 爲結尾命名。 // 建議使用 personImageView let personImage: UIImageView // 這個不是String,應該命名爲 textLabel let text: UILabel // animation 不能清晰表達出時間間隔 // 建議使用 animationDuration 或 animationTimeInterval let animation: NSTimeInterval // transition 不能清晰表達出是String // 建議使用 transitionText 或 transitionString let transition: String // 這個是ViewController,不是View let popupView: UIViewController // 因爲不建議使用縮寫,這裏建議使用 ViewController替換 VC let popupVC: UIViewController // 技術上講這個變量是 UIViewController, 但應該表達出這個變量是TableViewController let popupViewController: UITableViewController // 爲了保持一致性,建議把類型放到變量的結尾,而不是開始,如submitButton @IBOutlet weak var btnSubmit: UIButton! @IBOutlet weak var buttonSubmit: UIButton! // 在使用outlets 時,變量名內應包含類型名。 // 這裏建議使用 firstNameLabel @IBOutlet weak var firstName: UILabel! }
推薦 var names: [String] = [] var lookup: [String: Int] = [:] 不推薦 var names = [String]() var names: Array<String> = [String]() / 不夠簡潔 var lookup = [String: Int]() var lookup: Dictionary<String, Int> = [String: Int]() // 不夠簡潔
推薦 class TestTabelViewCell: UITableViewCell { static let kCellHeight = 80.0 /* ... */ } // uses let cellHeight = TestTabelViewCell.kCellHeight 不推薦 let kCellHeight = 80.0 class TestTabelViewCell: UITableViewCell { /* ... */ } // uses let cellHeight = kCellHeight
推薦 UIView.animate(withDuration: 1.0) { self.myView.alpha = 0 } 不推薦 UIView.animate(withDuration: 1.0, animations: { self.myView.alpha = 0 })
推薦 let testArray = [1, 2, 3, 4, 5] 不推薦 let testArray = [1,2,3,4,5]
推薦 /// <#Description#> /// /// - Parameter testString: <#testString description#> /// - Returns: <#return value description#> func testFunction(testString: String?) -> String? { /* ... */ } 不推薦 // Comment func testFunction(testString: String?) -> String? { /* ... */ }
// MARK: -
,按功能和協議/代理分組/// MARK順序沒有強制要求,但System API & Public API通常分別放在第一塊和第二塊。 // MARK: - Public // MARK: - Request // MARK: - Action // MARK: - Private // MARK: - xxxDelegate
/** ## 功能列表 這個類提供下一下很讚的功能,以下: - 功能 1 - 功能 2 - 功能 3 ## 例子 這是一個代碼塊使用四個空格做爲縮進的例子。 let myAwesomeThing = MyAwesomeClass() myAwesomeThing.makeMoney() ## 警告 使用的時候總注意如下幾點 1. 第一點 2. 第二點 3. 第三點 */ class MyAwesomeClass { /* ... */ }
@available(iOS x.0, *) class myClass { } @available(iOS x.0, *) func myFunction() { }
推薦github
resource.request().onComplete { [weak self] response in guard let strongSelf = self else { return } let model = strongSelf.updateModel(response) strongSelf.updateUI(model) }
不推薦swift
// 不推薦使用unowned // might crash if self is released before response returns resource.request().onComplete { [unowned self] response in let model = self.updateModel(response) self.updateUI(model) }
不推薦api
// deallocate could happen between updating the model and updating UI resource.request().onComplete { [weak self] response in let model = self?.updateModel(response) self?.updateUI(model) }
推薦數組
func login(with username: String?, password: String?) throws -> LoginError { guard let username = contextusername else { throw .noUsername } guard let password = password else { throw .noPassword } /* login code */ }
不推薦安全
func login(with username: String?, password: String?) throws -> LoginError { if let username = username { if let password = inputDatapassword { /* login code */ } else { throw .noPassword } } else { throw .noUsername } }
class TestManager { static let shared = TestManager() /* ... */ }
1 使用四個空格進行縮進。閉包
2 每行最多160個字符,這樣能夠避免一行過長。 (Xcode->Preferences->Text Editing->Page guide at column: 設置成160便可)app
3 確保每一個文件結尾都有空白行。ide
4 確保每行都不以空白字符做爲結尾 (Xcode->Preferences->Text Editing->Automatically trim trailing whitespace + Including whitespace-only lines).
5 左大括號不用另起一行。
遵照Xcode內置的縮進格式( 若是已經遵照,按下CTRL-i 組合鍵文件格式沒有變化)。當聲明的一個函數須要跨多行時,推薦使用Xcode默認的格式
// Xcode針對跨多行函數聲明縮進 func myFunctionWithManyParameters(parameterOne: String, parameterTwo: String, parameterThree: String) { // Xcode會自動縮進 print("\(parameterOne) \(parameterTwo) \(parameterThree)") } // Xcode針對多行 if 語句的縮進 if myFirstVariable > (mySecondVariable + myThirdVariable) && myFourthVariable == .SomeEnumValue { // Xcode會自動縮進 print("Hello, World!") }
someFunctionWithManyArguments( firstArgument: "Hello, I am a string", secondArgument: resultFromSomeFunction() thirdArgument: someOtherLocalVariable)
當遇到須要處理的數組或字典內容較多須要多行顯示時,需把 [ 和 ] 相似於方法體裏的括號, 方法體裏的閉包也要作相似處理。
someFunctionWithABunchOfArguments( someStringArgument: "hello I am a string", someArrayArgument: [ "dadada daaaa daaaa dadada daaaa daaaa dadada daaaa daaaa", "string one is crazy - what is it thinking?" ], someDictionaryArgument: [ "dictionary key 1": "some value 1, but also some more text here", "dictionary key 2": "some value 2" ], someClosure: { parameter1 in print(parameter1) })
應儘可能避免出現多行斷言,可以使用本地變量或其餘策略。
// 推薦 let firstCondition = x == firstReallyReallyLongPredicateFunction() let secondCondition = y == secondReallyReallyLongPredicateFunction() let thirdCondition = z == thirdReallyReallyLongPredicateFunction() if firstCondition && secondCondition && thirdCondition { // 你要幹什麼 } // 不推薦 if x == firstReallyReallyLongPredicateFunction() && y == secondReallyReallyLongPredicateFunction() && z == thirdReallyReallyLongPredicateFunction() { // 你要幹什麼 }
// 指定類型 let pirateViewController: PirateViewController // 字典語法(注意這裏是向左對齊而不是分號對齊) let ninjaDictionary: [String: AnyObject] = [ "fightLikeDairyFarmer": false, "disgusting": true ] // 聲明函數 func myFunction<t, u: someprotocol where t.relatedtype == u>(firstArgument: U, secondArgument: T) { /* ... */ } // 調用函數 someFunction(someArgument: "Kitten") // 父類 class PirateViewController: UIViewController { /* ... */ } // 協議 extension PirateViewController: UITableViewDataSource { /* ... */ }
二元運算符(+, ==, 或->)的先後都須要添加空格,左小括號後面和右小括號前面不須要空格。
let myValue = 20 + (30 / 2) * 3 if 1 + 1 == 3 { fatalError("The universe is broken.") } func pancake() -> Pancake { /* ... */ }
1 多使用let,少使用var
2 少用!
去強制解包
3 可選類型拆包取值時,使用if let
判斷
4 不要使用 as! 或 try!
5 數組訪問儘量使用 .first 或 .last, 推薦使用 for item in items 而不是 for i in 0..
6 若是變量可以推斷出類型,則不建議聲明變量時指明類型
7 若是變量可以推斷出類型,則不建議聲明變量時指明類型
8 switch case選項不須要使用break
關鍵詞
9 訪問控制
10 對於私有訪問,若是在文件內不能被修改,則標記爲private
;若是在文件內可修改,則標記爲fileprivate
11 對於公有訪問,若是不但願在外面繼承或者override,則標記爲public
,不然標明爲open
12 訪問控制權限關鍵字應該寫在最前面,除了@IBOutlet
、IBAction
、@discardableResult
、static
等關鍵字在最前面
13 如調用者能夠不使用方法的返回值,則須要使用@discardableResult
標明
14 使用==
和!=
判斷內容
上是否一致
15 使用===
和!==
判斷class類型對象是否同一個引用,而不是用 ==
和!=
16 Runtime兼容
17 Swift語言自己對Runtime並不支持,須要在屬性或者方法前添加dynamic修飾符才能獲取動態型,繼承自NSObject的類其繼承的父類的方法也具備動態型,子類的屬性和方法也須要加dynamic才能獲取動態性
1 Swift接口不對Objective-C兼容,在編譯器或者Coding中就會出現錯誤
2 暴漏給Objective-C的任何接口,須要添加@objc關鍵字,若是定義的類繼承自NSObject則不須要添加
3 若是方法參數或者返回值爲空,則須要標明爲可選類型
[參考文獻]: