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 若是方法参数或者返回值为空,则须要标明为可选类型
[参考文献]: