SwiftLint代码规范属性详细说明
- 属性1 : weak_delegate 。 代理应该写成weak类型(弱代理)来避免循环引用
例如:
/// 1.1 编译通过
class Langke {
var chenlong: NSObjectProtocol?
}
/// 1.2 编译通过,但是触发swiftlint的 weak_delegate警告, 原因是变量名 myDelegate 中有 delegate 关键字,这属于名字滥用
class Langke {
var myDelegate: NSObjectProtocol?
}
/// 1.3 编译通过, 不会触发警告, 原因是在 var 关键字前面加了 weak
class Langke {
weak var myDelegate: NSObjectProtocol?
}
/// 2.1 编译通过,但是触发 weak_delegate 警告,原因是 scrollDelegate 中 Delegate 放在了最后, 被理解成了代理
class Langke {
var scrollDelegate: UIScrollViewDelegate?
}
/// 2.2 编译通过, 既然变量名被理解成了代理, 那为了类似防止循环引用, 应该加关键字 weak
class Langke {
weak var scrollDelegate: UIScrollViewDelegate?
}
/// 编译通过, 不会触发警告, 因为delegate放在了前面, 没有被理解成代理
class Langke {
var delegateScroll: UIScrollViewDelegate?
}
总结, 如果要使用swiftlint中的这个 weak_delegate 属性, 当你所定义的变量名被理解成某某代理时, 则需要加关键字 weak 来消除warning, 最好的方式是别乱取名字, 比如这样取名也是错误的:var delegate: String?, 这也会trigger swiftlint warning!
- 属性2 : void_return 。 返回值为空,我们一般推荐用 ” -> Void “, 而不是 ” -> () “, 主要针对全局变量/常量闭包:如let xingYun: () -> () = {}
例如:
/// 触发void_return 和 属性46:redundant_void_return
func XingYun() -> () {
print("星云摁羊不厉害!")
}
// 触发void_return
let xingYun: () -> ()
/// 不触发 void_return, 但是会触发属性46: redundant_void_return
func XingYun() -> Void {
print("星云摁羊很厉害!")
}
// 不触发
let xingYun: () -> Void
总结, 返回为空全部统一用关键字 Void, 不要用 ()
- 属性3 : vertical_whitespace 。 垂直方向上的空格行,限制为一行(注释除外),
例如:
/// 没有空格, nonTriggerWarning
override func viewDidLoad() {
super.viewDidLoad()
let aaa = 0
}
/// 有一行空格, nonTriggerWarning
override func viewDidLoad() {
super.viewDidLoad()
let aaa = 0
............................1
}
/// >=2行,就会触发警告
override func viewDidLoad() {
super.viewDidLoad()
let aaa = 0
.............................1
.............................2
}
这个推荐到项目中,垂直方向行间数最多为1, 这样可以保证code的饱满性、可读性
- 属性4 : variable_name 。 变量名应该只包含字符数字字符, 并且只能以小写字母开头或者应该只包含大写字母。此外,当变量名被声明为static(静态)变量时或者immutable不可变的时候,这时或许可以以一个大写字母开头。最后,变量名不应该太长或者太短(应该在3-40个字符间,否则会触发警告!!!)。注意:目前变量名只适用于自己写的方法的参数和自己写的class中的全局常量或变量, 对于系统自带的方法里面和自己写的方法里面没有作用
例如:
本例来自于官方文档
nonTriggeringExamples: [
"let myLet = 0",
"var myVar = 0",
"private let _myLet = 0",
"class Abc { static let MyLet = 0 }",
"let URL: NSURL? = nil",
"let XMLString: String? = nil"
],
triggeringExamples: [
"↓let MyLet = 0",
"↓let _myLet = 0", //这里我就郁闷了,这样命名不可以?
"private ↓let myLet_ = 0",
"↓let myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0",
"↓var myExtremelyVeryVeryVeryVeryVeryVeryLongVar = 0",
"private ↓let _myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0",
"↓let i = 0",
"↓var id = 0",
"private ↓let _i = 0"
]
属性5 : valid_ibinspectable 。 @IBInspectable在swiftlint中的使用需要注意, 第一必须是变量, 第二必须要有指定的类型,如果指定的类型是可选类型或者隐式类型,则目前官方只支持以下几种类型:
String, NSString, UIColor, NSColor, UIImage, NSImage.
例如:
/// 指定为变量var, 类型为String?和String!
@IBInspectable private var yyy: String?
@IBInspectable private var zzz: String!
/// 如果写成这样,编译能通过,但是会触发警告, 因为swiftlint暂不支持Int可选和隐式类型:
@IBInspectable private var dddl: Int!
@IBInspectable private var eeel: Int?
/// 如果指定的类型不是可选类型, 就应该初始化,否则系统不允许,会报错所在的类没有初始化
对:
@IBInspectable private var counts: Int = 0
系统报错:
@IBInspectable private var counts: Int
- 属性6 : file_header 。文件头。文件应该有一致的注释, 主要看下面例子:
例如:
/// 不会触发warning
如果我新建一个工程,在ViewController.swift文件中, 开始的注释应该是:
//
// ViewController.swift
// SwiftLint
//
// Created by langke on 17/1/17.
// Copyright © 2017年 langke. All rights reserved.
//
改变一下变为:
//
// MyViewController.swift...................由于这里和外面的文件名不一样,所以触发warning(实际上在swift 3.0上测试这个属性暂时没有任何作用!!)
// SwiftLint
//
// Created by langke on 17/1/17.
// Copyright © 2017年 langke. All rights reserved................官方terminal表示,Copyright和Created没有对齐,也会触发warning!!!
//
- 属性7 : prohibited_super_call 。被禁止的父类响应。一些方法不应该响应父类。
例如:
/// 不会触发warning
class VC: UIViewController {
override func loadView() {
}
}
class NSView {
func updateLayer() {
self.method1()
}
}
/// 会触发warning
class VC: UIViewController {
override func loadView() ↓{
super.loadView()
}
}
class VC: NSFileProviderExtension {
override func providePlaceholder(at url: URL, completionHandler: @escaping (Error?) -> Void) ↓{
self.method1()
super.providePlaceholder(at:url, completionHandler: completionHandler)
}
}
class VC: NSView {
override func updateLayer() ↓{
self.method1()
super.updateLayer()
self.method2()
}
}
- 属性8 : colon 。冒号的使用, swiftlint的这个colon属性规则很简单,要求“ :”紧靠所定义的常量或变量等,必须没有空格,与所指定的类型之间必须只有一个空格,多一个或少一个都不行,如果是用在Dictionary中,则要求紧靠Key,与Value之间必须有且仅有一个空格。这个规则我觉得应该强制推荐使用。由于简单,就不举例子了。
- 属性9 : comma 。逗号规则, 冒号的使用可以使代码看起来不让人感到那么疲惫、头疼, 使用只要遵循“前不离身后退一步”就行了,这个也强制推荐使用。
属性10 : trailing_newline 。尾部新行,官方文档给出的description是:”Files should have single trailing newline”, 也就是说,文件(属性、方法)结束的的时候(“}”之前), 应该有一个空格新行,但这里要注意的是, 只是应该, 而不是必须, 所以这个属性也算是一个可选属性。官方给出的例子是这样的:
/// 空一行,不会触发警告 nonTriggeringExamples: [ "let a = 0\n" ], /// 下面会触发警告 triggeringExamples: [ "let a = 0", /// 不空行,会触发警告(实际上,我试过,不会触发警告) "let a = 0\n\n" /// 空两行, 会触发警告(实际上,我试过,会触发警告,但是触发的是vertical_whitespace警告而不是trailing_newline) ], /// 说说这里,它要求改正为都空一行,虽然这样code看起来很轻松,但如果定义变量或常量太多,就太分散了(值得说的是,就算不空行也不会触发trailing_newline, 应该刚才也已经说了,这个属性只是说“应该”,而不是必须) corrections: [ "let a = 0": "let a = 0\n", "let b = 0\n\n": "let b = 0\n", "let c = 0\n\n\n\n": "let c = 0\n" ]
既然如此,那这个属性什么时候回触发,具体的触发是在哪个地方呢?我自己测试了一下,这个方法的触发是在当前所在类的页面中的闭包最外面的尾部,也就是在“ }”的后面有一个空格新行,或者没有空格新行,如果 >= 2 则就会触发trailing_newline警告,比如:
}..............第40行
...............第41行空行
...............第42行空行--------