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行空行-------->触发警告
这个属性是swiftlint的一个随意的属性,如果对代码要求style特别严格的那就用一下吧,其他几乎没有什么影响。
- 属性11 : trailing_whitespace 。 尾部空白行,这个强烈不推荐使用。看下面例子:
例如:
/// 下面这个例子不会触发警告,但是一旦其中有一个空行就会触发警告trailing_whitespace, 这和vertical_whitespace实质上有些冲突,vertical_whitespace要求两行code之间不超过1行,要么没有空行,要么只有1行,而trailing_whitespace要求没有空行!!!
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let a = 0
let b = 1
let c = 2
}
func chenlong() -> Void {
let a = 0
print(a)
}
}
这个属性强烈不推荐,代码之间不允许有一个空行,这会使程序的可读性差,所以希望禁用!!!
属性12 : line_length 。行的字符长度属性。这个强烈不推荐使用。官方的规定是超过120字符就给warning, 超过200个字符就直接报error!!!我们又不是写底层脚本的,所以建议这种方式禁用!!
属性13 : mark 。 标记方法或者属性。这个推荐使用, 可以统一方法标记的格式, 有利于review查找某个方法或者属性的时候更清晰。使用也非常简单: “MARK”前空一格,”MARK:”后空一格。
属性14 :todo 。TODO 和 FIXME 应该避免使用, 使用“notaTODO 和 notaFIXME”代替。另外, 和 MARK 标记不同的是, “notaTODO 和 notaFIXME”没有空格要求,但是我建议如果要使用这个 todo 属性, 尽量写成和 MARK 一样的规范。
属性15 : trailing_comma 。尾部逗号, 这个强烈推荐使用, 这个属性主要针对数组和字典最后一个元素。
例如:
/// 数组这样写是没有任何问题的, 但是最后一个元素3后面加了一个逗号“,”尽管这样不会报错,但是这会让程序的可读性变差
let ages = [1, 2, 3,]
let person = ["XingYun": 98, "JinGang": 128, "LangKe": 18,]
/// 使用swiftlint的trailing_comma规则后,就会报warning, 所以正确的写法不应该加上这个“,”
let ages = [1, 2, 3]
let person = ["XingYun": 98, "JinGang": 128, "LangKe": 18]
属性16 : trailing_semicolon 。末尾分号, 强烈推荐使用,尽管在变量或常量赋值之后加不加分号在swift中没有硬性的要求,但是为了使code style更swift化,所以尽量或者绝对不要加“;”。
属性17 : closing_brace 。封闭大括号, 大括号和括号中间不应该有任何的空格, 也就是 “{}”和“()”不能有空格, 这个属性推荐使用。
例如:
/// 没问题
({})
/// 有问题
( {})
/// 有问题
({} )
- 属性18 : closure_end_indentation 。 闭包结束缩进, 什么意思呢?就是 大括号(一般是方法)上下对齐的问题,这样使code看起来更加整洁。
例如:
/// 必须注意的是,大括号左边“{”前面有一个空格,没有则会触发closure_end_indentation警告
langke.beginFishing {.........
.............
}
- 属性19 : closure_spacing 。 闭包空格,闭包表达式在每个大括号内应该有一个单独的空格, 要注意的是这里指的是“应该”, 我自己测试了一下,在swift 3.0并没有报warning, 所以这也不是强制性要求,但这个推荐使用。
例如:
[].filter { content }
- 属性20 : closure_parameter_position 。 闭包参数位置, 闭包参数应该和大括号左边在同一行, 推荐使用。
例如:
/// number 和 { 在同一行
let names = [1, 2, 3]
names.forEach { (number) in
print(number)
}
let names = [1, 2, 3]
names.map { number in
number + 1
}
/// 这样不行,违背 closure_parameter_position规则, 触发warning
let names = [1, 2, 3]
names.forEach {
(number) in
print(number)
}
let names = [1, 2, 3]
names.map {
number in
number + 1
}
属性21 : dynamic_inline 。动态–内联, 避免一起使用 dynamic 和 @inline(_ _always), 否则报 error
例如:
/// 正确的做法
class LangKe {
dynamic func myFunction() {
}
}
class LangKe {
@inline(__always) func myFunction() {
}
}
class LangKe {
@inline(never) dynamic func myFunction() {
}
}
/// 只要同时使用 dynamic 和 @inline(_ _always)都报错 error!!!
class LangKe {
@inline(__always) public dynamic func myFunction() {
}
}
这个属性这样做我也不知道什么原因, dynamic 和 @inline(__always) 不能同时使用, 不过既然它这样做,那必然有着它的道理, 所以这个属性也推荐使用。
- 属性22 : unused_closure_parameter 。 不使用的闭包参数, swiftlint建议最好不使用的闭包参数使用 “_”代替。推荐使用。
例如:
/// 不会触发warning
[1, 2].map { _ in
return 3
}
/// 会触发warning
[1, 2].map { number in
return 3
}
- 属性23 : compiler_protocol_init 。 编译器协议初始化, 属性在swiftlint的有着例子,但是我在swift 3.0中运行并没有起到任何作用, 所以这个属性是否需要使用待定。不过仔细在 terminal上使用 swiftlint rules 查看了一下,并没有发现compiler_protocol_init属性,也许是新加的属性,还没有集成到new version上?
例如官方的完整讲解是这样的:
public static let description = RuleDescription(
identifier: "compiler_protocol_init",
name: "Compiler Protocol Init",
description: "The initializers declared in compiler protocols such as `ExpressibleByArrayLiteral` " +
"shouldn't be called directly.",
/// 不会触发警告
nonTriggeringExamples: [
"let set: Set<Int> = [1, 2]\n",
"let set = Set(array)\n"
],
/// 会触发warning(实际上我在swift 3.0中测试过,根本就不会触发swiftlint的warning)
triggeringExamples: [
"let set = ↓Set(arrayLiteral: 1, 2)\n",
"let set = ↓Set.init(arrayLiteral: 1, 2)\n"
]
)
- 属性24 : control_statement 。 控制语句, if、for、while、do语句不应该将 条件 写在 圆括号 中, 另外注意条件出的空格。
例如:
nonTriggeringExamples: [
"if condition {\n",
"if (a, b) == (0, 1) {\n",
"if (a || b) && (c || d) {\n",
"if (min...max).contains(value) {\n",
"if renderGif(data) {\n",
"renderGif(data)\n",
"for item in collection {\n",
"for (key, value) in dictionary {\n",
"for (index, value) in enumerate(array) {\n",
"for var index = 0; index < 42; index++ {\n",
"guard condition else {\n",
"while condition {\n",
"} while condition {\n",
"do { ; } while condition {\n",
"switch foo {\n"
],
triggeringExamples: [
"↓if (condition) {\n", /// 有 “()”, warning
"↓if(condition) {\n", /// if 和 条件之间没空格, 而且有 “()”
"↓if ((a || b) && (c || d)) {\n",
"↓if ((min...max).contains(value)) {\n",
"↓for (item in collection) {\n",
"↓for (var index = 0; index < 42; index++) {\n",
"↓for(item in collection) {\n",
"↓for(var index = 0; index < 42; index++) {\n",
"↓guard (condition) else {\n",
"↓while (condition) {\n",
"↓while(condition) {\n",
"} ↓while (condition) {\n",
"} ↓while(condition) {\n",
"do { ; } ↓while(condition) {\n",
"do { ; } ↓while (condition) {\n",
"↓switch (foo) {\n"
]
这个属性保证了代码的简洁性, 一般而言,在swift中的条件句中尽量不加括号, 直接写条件,除非特别需要! 另外注意条件前后的空格,一般都有一个空格,这个属性推荐使用。
属性25 : custom_rules 。 自定义规则。 这个属性可以通过提供正则表达式来创建自定义规则, 可选指定语法类型搭配, 安全、级别和要陈列的什么信息。 这个属性只要熟悉使用正则表达式的人使用,目前可以不适用。
属性26 : cyclomatic_complexity 。循环复杂度。函数体的复杂度应该要限制,这个属性主要约束条件句、循环句中的循环嵌套问题, 当嵌套太多的循环时,则会触发swiftlint中的warning和error,当达到10个循环嵌套时就会报warning,达到20个循环嵌套时就会报error,强烈推荐这个属性。嵌套太多,可读性差!
例如:
// warning or error
func LangKe() -> Void {
if true {
if false {
guard true else { return }
if false {
...............循环复杂
}
}
}
}
- 属性27 : empty_count 。比起检查 count 是否为 0 , swiftlint上说更喜欢检测 “isEmpty”。
例如:
/// swiftlint不喜欢这样使用
let number = "long"
if number.characters.count == 0 {
print("为空")
} else {
print("不为空")
}
/// swiftlint更喜欢这种正式风格
if number.isEmpty {
print("为空")
} else {
print("不为空")
}
这个属性推荐使用, 尽管我在swift 3.0上测试并没有触发警告, 但是这是一个比较好的约束, 可以规范开发者对语法的使用, 同时更符合swift的风格。
- 属性28 : statement_position 。 陈述句位置, 这里主要指的是 else 和 catch 前面要加一个空格, 也不能大于1个空格, 否则就会触发警告。
例如:
/// 没有空格,触发warning
let number = "long"
if number.isEmpty {
print("为空")
}else {.............................注意这里
print("不为空")
}
/// 这里也会触发warning, 因为else if换行了
let number = "long"
if number.isEmpty {
print("为空")
}
else if number.contains("long") {............................注意这里
print("不为空")
} else {
print("s")
}
/// 正确的写法
let number = "long"
if number.isEmpty {
print("为空")
} else {
print("不为空")
}
- 属性29 : opening_brace 。在声明的时候, 左大括号应该有一个空格,并且在同一行,推荐使用。
例如:
/// trigger warning
let number = "long"
if number.isEmpty {
print("为空")
} else{............................注意这里
print("s")
}
/// nonTrigger warning
let number = "long"
if number.isEmpty {
print("为空")
} else {
print("s")
}
当然,如果有小括号的时候, 就不要有空格, 比如:({ })——->这是属性 closing_brace的规则。
- 属性30 : empty_parameters 。为空参数。swiftlint更喜欢 “()->” 比起 “Void ->”
例如:
/// 01 不会触发warning
let abc: () -> Void
func foo(completion: () -> Void) {
}
/// 02 直接报错
let bcd: Void -> Void
func foo(completion: Void -> Void) {
}
/// 03 在终端上查看swiftlint rules, 应该只会报warning, 但是直接报error, 然后系统提示 “02”应该改为:
let bcd: (Void) -> Void
func foo(completion: (Void) -> Void) {
}
- 属性31 : empty_parentheses_with_trailing_closure 。尾随闭包中使用空的圆括号, 在使用尾随闭包的时候, 应该尽量避免使用空的圆括号, 是否使用待定。
例如:
/// 触发warning
[1, 2].map() { $0 + 1 }
[1, 2].map( ) { $0 + 1 }
[1, 2].map() { number in\n number + 1 \n}
[1, 2].map( ) { number in\n number + 1 \n}
/// 不会触发warning
[1, 2].map { $0 + 1 }
[1, 2].map { $0 + 1 }
[1, 2].map { number in\n number + 1 \n}
[1, 2].map { number in\n number + 1 \n}
-
属性32 : file_length 。 文件长度。 这个属性我在swift 3.0上测试并没有起到任何作用, 官方给的内容是:
identifier: "file_length",
name: "File Line Length",
description: "Files should not span too many lines.",
nonTriggeringExamples: [
repeatElement("//\n", count: 400).joined()
],
triggeringExamples: [
repeatElement("//\n", count: 401).joined()
] 属性33 : force_cast 。强制转换, 强制转换应该被避免,否则直接报 error。
例如:
/// 正确转换
NSNumber() as? Int
/// 直接报错, 不要强制转换
NSNumber() as! Int
这个force_cast强制转换属性, 至于是否使用还有待商榷。
- 属性34 : force_try 。 强制尝试, swiftlint禁止使用强制尝试, 否则直接报 error。
例如:
/// 这样写是可以的,不会触发 error
func myFunction() throws {
}
do {
try myFunction()
} catch {
}
/// 这样直接触发 error
func myFunction() throws {
}
try! myFunction()
属性35 : function_body_length 。函数体长度, 函数体不应该跨越太多行, 超过40行给warning, 超过100行直接报错。推荐使用。
属性36 : function_parameter_count 。函数参数个数, 函数参数数量(init方法除外)应该少点, 不要太多,swiftlint规定函数参数数量超过5个给warning, 超过8个直接报error。这个属性推荐使用, 由于简单就不举例了。注:function_parameter_count: error 这样并不能改变它的警告或错误,该属性不允许修改,但是可以禁用
属性37 : imlicit_getter 。隐式getter方法。计算的只读属性应该避免使用 get 关键字, 也就是说, 如果只是为了只读, 那就可以直接返回就行, 而不用写 get 关键字, 如果既可读又可写,那就可以写。
例如:
/// 报warning
var foo: Int {
get{
return 20
}
}
/// 应该写成这样(直接写)
var foo: Int {
return 20
}
总结: 也就是说, 如果只有 get 一个关键字, 就不能写 get, 如果除 get关键字外,还有 set, 那就可以写 get , 再简化说:只读计算属性省略get, 可读可写不省略get, 当然, 这只针对 计算只读属性 的时候。
- 属性38 : legacy_cggeometry_functions 。遗留的CG几何函数, 当获取某个视图的宽、高、最小X、最大X值等等, swiftlint推荐使用swift的标准语法, 尽量不要使用从Objective-C中的遗留版本, 尽量语法swift化。
例如:
/// 这样不推荐使用
CGRectGetWidth(someView.frame)
/// 推荐使用下面的形式
rect.width
rect.height
rect.minX
rect.midX
rect...................
/// 我在swift 3.0, Xcode 8.1中作如下尝试, 编译直接失败,报错:CGRectGetMaxX has been replaced by property CGRect.maxX
let myLabel = UILabel(frame: CGRect(x: CGRectGetMaxX(myView.frame), y: 22, width: 33, height: 44))
/// 根据**系统**提示信息改正如下
let myLabel = UILabel(frame: CGRect(x: myView.frame.maxX, y: 22, width: 33, height: 44))
总结:swiftlint已经将这个属性紧靠系统原生API, OC带过来的CG几何函数很多已被弃用, 这个属性强烈推荐使用。
- 属性39 : legacy_constant 。遗留版本常数, 和属性38(legacy_cggeometry_functions)一样, 结构范围常数尽量分开、明确、具体, 不要使用OC的遗留整体常数。
例如:
/// 规范的写法,不会触发warning
CGPoint.zero
/// 不规范的写法, 会触发warning
CGPointZero
CGRectZero
推荐使用这样的语法, 而且swift 3.0已经开始强制使用这种规范的点语法了。
- 属性40 : legacy_constructor 。遗留版本构造器, swiftlint要求系统自带构造器, 使用swift语法化, 不要使用OC版本的构造器。
例如:
/// swift语法, swift 3.0已经强制使用了,所以尽管swiftlint不定制这种规则, 系统也会强制规定使用
CGPoint(x: 10, y: 20)
/// 错误的构造器语法
CGPointMake(10, 20)
- 属性41 : legacy_nsgeometry_functions 。 ns类几何函数, 和前面的几个属性一样, 使用swift点语法函数, 不使用以前的版本。
例如:
/// 正确
view.width/height/minX
/// 错误
NSWidth(view.frame)
- 属性42 : operator_usage_whitespace 。操作符使用规则, 操作符两边应该有空格。比如 “+” “-” “??”
例如:
let sum = 1 + 2
let mutiplier = 2 * 3
let devide = 10 /2
- 属性43 : overridden_super_call 。 重写父类方法, 强烈推荐使用。
例如:
/// 正确的写法
override func viewWillAppear(_ animated: Bool) {
/// 注意重写父类方法
super.viewWillAppear(animated)
}
*属性44 : private_outlet 。私人输出, IBOutlet 这个属性应该是私人的, 为了避免泄露UIKit到更高层, 官方:”IBOutlets should be private to avoid leaking UIKit to higher layers.”
例如:
/// swiftlint 建议当使用 IBOutlet属性的时候, 在其后面加一个 private 表示私有的, 但是我在swift 3.0上测试, 尽管使用了swiftlint, 但并没有起到任何作用
// swiftlint建议不能下面这样写
class LangKe {
@IBOutlet var label: UILabel?
}
/// swiftlint 建议这样写
class LangKe {
@IBOutlet private var label: UILabel?
}
- 属性45 : redundant_string_enum_value 。 多余的字符串枚举值, 在定义字符串枚举的时候, 不要让枚举值和枚举成员名相等
例如:
// warning 1
enum Numbers: String {
case one = "one"
case two
}
enum Numbers: String {
case one
case two = "two"
}
enum Numbers: String {
case one = "one"
case two = "two"
}
当然, 只要有一个case 的成员名和枚举值不相等, 那就没有warning, 比如:
enum Numbers: String {
case one = "ONE"
case two = "two"
}
- 属性46 : redundant_void_return 。多余的返回值为空, 在函数声明的时候,返回值为空是多余的。定义常量或者变量的时候可以。
例如:
/// 这个属性要求这样写, 返回值为空省略
func XingYun() {
print("摁��")
}
/// 这个属性要求别这样写,否则会有warning(但是我在swift 3.0上测试并没有触发warning)
func XingYun() -> Void {
print("摁��")
}
注意: 在属性2中, void_return中, 喜欢 “-> Void”胜过于 “-> ()”, 这并不代表使用 -> Void 很好, 我觉得省略比较好, 所以这个属性推荐使用 。
- 属性47 : return_arrow_whitespace 。 返回箭头空格, swiftlint推荐返回箭头和返回类型应该被空格分开, 也就是 “->”和 type 之间有空格。
例如:
/// 报warning
func XingYun() ->Int {
print("摁牛")
return 22
}
/// 不报warning ------> 推荐使用
func XingYun() -> Int {
print("摁牛")
return 22
}
/// swiftlint 不反对“->”和“type”之间换行, 不报warning ------> 但是不推荐使用
func XingYun() ->
Int {
print("摁牛")
return 22
}
属性48 : type_name 。类型名, 类型名应该只包含字母数字字符, 并且以大写字母开头,长度在3-40个字符。这个属性没什么好说的,强烈推荐使用。
属性49 : syntactic_sugar 。语法糖, swiftlint推荐使用速记语法糖, 例如 [Int] 代替 Array, 强烈建议推荐使用。
例如:
/// 触发warning
let myArray: Array<Int> = [1, 2, 3]
print(myArray)
/// 正确写法,不会触发warning
let myArray: [Int] = [1, 2, 3]
print(myArray)
- 属性50 : switch_case_on_newline 。switch语句新行, 在switch语法里, case应该总是在一个新行上面。 看看例子就知道了。
例如:
/// swiftlint表示会触发warning
switch type {
case .value1: print("1")...................在同一行错
case .value2: print("2")...................在同一行错
default: print("3")...................在同一行错
}
/// 不会触发warning
switch type {
case .value1:
print("1")
case .value2:
print("2")
default:
print("3")
}
总结来说,就是要求在switch语句中,case要求换行。这个属性强烈推荐使用。
- 属性51 : shorthand_operator 。速记操作符, 什么是速记操作符呢? 在swiftlint中, 就是我们常用的简洁操作运算符,比如:+= , -=, *=, /= 等等。在swiftlint中,在做一些赋值操作的时候,推荐使用简短操作符。
例如:
/// 不推荐使用(在swift 3.0上并不会触发warning或error)
var value = 4
value = value / 2
print(value)
/// 推荐使用
var value = 4
value /= 2
print(value)
- 属性52 : sorted_imports 。 分类/有序导入。 这个属性有些奇怪, 要求导入的时候导入的类要按顺序导入。另外,这个属性暂时在terminal上使用swiftlint rules是没有的。直接看官方给的示例:
例如:
identifier: "sorted_imports",
name: "Sorted Imports",
description: "Imports should be sorted.",
nonTriggeringExamples: [
"import AAA\nimport BBB\nimport CCC\nimport DDD"
],
triggeringExamples: [
"import AAA\nimport ZZZ\nimport ↓BBB\nimport CCC"
]
这个属性不推荐使用,导入的时候没必要按顺序来导入,一般来说,在项目中你也不会导入太多的类,特别是在swift语言中。
- 属性53 : number_separator 。数字分割线。当在大量的小数中, 应该使用下划线来作为千分位分割线。推荐使用。
例如:
/// 推荐使用这种形式
let xxx = 1_000_000_000.000_1
print(xxx)
/// 不推荐使用这种形式(在swift 3.0上无warning,也就是说这个属性暂时并未起到任何作用)
let xxx = 1000000000.0001
print(xxx)
- 属性54 : nimble_operator 。 敏捷操作符。和*匹配函数相比, 更喜欢敏捷操作符, 比如:>=、 ==、 <=、 <等等。
例如:
/// 会触发warning
(person.voice).toNot(equal("Hello world")) // 人的声音不等于“Hello world”
10.to(beGreaterThan(5)) // 10比5大
99.to(beLessThan(100)) // 99比100小
// 改为以下
(person.voice) != "Hello world" // 人的声音不等于“Hello world”
10 > 5 // 10比5大
99 < 100 // 99比100小
- 属性55 : nesting 。嵌套。类型嵌套至多一级结构, 函数语句嵌套至多五级结构。
例如:
/// no warning
func langke() {
func xingyun() {
func caicai() {
func xiaohui() {
func jingang() {
}
}
}
}
}
/// trigger warning
func langke() {
func xingyun() {
func caicai() {
func xiaohui() {
func jingang() {
//开始触发警告
func beginTriggerWarning() {
}
}
}
}
}
}
- 属性56 : redundant_optional_initialization。 多余的可选初始化, 可选变量初始化为 nil 时是多余的,官方描述:description: “Initializing an optional variable with nil is redundant.”。
例如:
/// 触发warning(实际上在swift 3.0上并没有触发)
var myVar: Int? = nil
var myVar: Optional<Int> = nil
var myVar: Int?=nil
var myVar: Optional<Int>=nil
/// 正确的写法
var myVar: Int?
var myVar: Optional<Int>
var myVar: Int?
var myVar: Optional<Int>
这个属性可以使用,虽然暂时在terminal上没有,但后续应该会集成到相应的swiftlint环境中。
- 属性57 : leading_whitespace 。文件开始不应该有空格或者换行, 否则就会触发warning
例如:
/// 不会触发warning
//
// ViewController.swift
// SwiftLint
//
// Created by langke on 17/1/12.
// Copyright © 2017年 langke. All rights reserved.
//
/// 会触发warning
//..................................这里有一个空格
// ViewController.swift
// SwiftLint
//
// Created by langke on 17/1/12.
// Copyright © 2017年 langke. All rights reserved.
//
/// 会触发warning
......................................这里是一个空行
//
// ViewController.swift
// SwiftLint
//
// Created by langke on 17/1/12.
// Copyright © 2017年 langke. All rights reserved.
//
- 属性58 : vertical_parameter_alignment 。垂直方向上的参数对齐。当函数参数有多行的时候, 函数参数在垂直方向上应该对齐(参数换行的时候左边对齐)。这个属性在 terminal 上使用 swiftlint rules查看目前是没有的。
例如:
nonTriggeringExamples: [
func validateFunction(_ file: File, kind: SwiftDeclarationKind,
dictionary: [String: SourceKitRepresentable]) { }
func validateFunction(_ file: File, kind: SwiftDeclarationKind,
dictionary: [String: SourceKitRepresentable]) -> [StyleViolation]
func validateFunction(_ file: File, kind: SwiftDeclarationKind,
dictionary: [String: SourceKitRepresentable])
-> [StyleViolation]
func validateFunction(
_ file: File, kind: SwiftDeclarationKind,
dictionary: [String: SourceKitRepresentable]) -> [StyleViolation]
func validateFunction(\n" +
_ file: File, kind: SwiftDeclarationKind,\n" +
dictionary: [String: SourceKitRepresentable]
) -> [StyleViolation]\n",
]
triggeringExamples: [
func validateFunction(_ file: File, kind: SwiftDeclarationKind,
dictionary: [String: SourceKitRepresentable]) { }
func validateFunction(_ file: File, kind: SwiftDeclarationKind,
dictionary: [String: SourceKitRepresentable]) { }
func validateFunction(_ file: File,
kind: SwiftDeclarationKind,
dictionary: [String: SourceKitRepresentable]) { }
]
- 属性59 : conditional_returns_on_newline 。条件返回语句应该在新的一行。 当有条件返回的时候应该换行返回,而不是在同一行。这个属性强烈推荐。
例如:
/// swiftlint 不推荐的写法, 否则会触发warning(但是在swift 3.0上测试并不会触发任何warning)
if true { return }
guard true else { return }
/// swiftlint 推荐的写法
if true {
return
}
guard true else {
return
}
- 属性60 : force_unwrapping 。 强制解包/拆包。我们知道,当一个类型是可选类型的时候,当我们获取值时,需要强制解包(也叫隐式解包), 通常我们是在一个变量或者所需要的常量、类型等后面加一个“ !”, 然而,swiftlint建议强制解包应该要避免, 否则将给予warning。
例如:
/// 将触发warning
navigationController!.pushViewController(myViewController, animated: true)
let url = NSURL(string: "http://www.baidu.com")!
print(url)
return cell!
/// 不会触发warning
navigationController?.pushViewController(myViewController, animated: true)
- 属性61 : explicit_init 。显式初始化。显式初始应该避免。
例如:
/// 使用显式初始化则触发warning(但实际上我在swift 3.0上测试并没有发现触发warning!!!)
[88].flatMap{ String↓.init($0) }
UITableView.init()
///正确的写法
[88].flatMap{ String($0) }
UITableView()
- 属性62 : missing_docs 。缺失说明注释, 官方解释:”Public declarations should be documented.”, 公共声明应该被注释/标记。 在函数声明的时候, 一般情况下, 带public关键字的函数的注释只能用 “///”和 “/* /”来注释, 如果不带public关键字的函数只能用 “//”和 “/* */” 。这个属性应该禁用,没必要!!!
例如:
不会触发warning
// public, documented using /// docs
/// docs
public func langke() {}
// public, documented using /** docs */
/** docs */
public func langke() {}
// internal (implicit), undocumented
func langke() {}
// internal (explicit) / private, undocumented
internal/private func langke() {}
1、协议成员被文件标记、注释, 但是继承的成员就不用
/// docs
public protocol A {
/// docs
var b: Int { get }
}
/// docs
public struct C: A {
public let b: Int
}
2、本地定义的父类成员被文件标记, 但是子类成员就不用
/// docs
public class A {
/// docs
public func b() {}
}
/// docs
public class B: A {
override public func b() {}
}
3、外部定义的父类成员被文件标记, 但是子类成员就不用
import Foundation
/// docs
public class B: NSObject {
// no docs
override public var description: String { fatalError() }
}
</br>
</br>
会触发warning(实际上在swift 3.0目前并不会触发!!)
// public , undocumented
public func langke() {}
// public , undocumented
// regular comment
public func a() {}
// public, undocumented
/* regular comment */
public func a() {}
// protocol member and inherited member are both undocumented
/// docs
public protocol A {
// no docs
var b: Int { get }
}
/// docs
public struct C: A {
public let b: Int
}
属性63 : valid_docs 。有效文件 。 文件声明应该有效 。这个属性和属性62有冲突, 而且重复, 官网文档写得有问题。另外在swift 3.0上测试并不会发生warning。暂时不举例,这个属性禁用!!!后期等官方完善之后再追加。
属性64 : type_body_length 。类型体长度。类型体长度不应该跨越太多行, 超过200行给warning,超过350行给error。一般是大括号或者括号内, 比如定义一个enum或struct。
例如:
class langke {
这里有201行,warning!!!
}
- 属性65 : redundant_nil_coalescing 。多余的为空联合操作符。为空联合操作符用来判断左边是否为空,伴随nil的为空操作符在右边是多余的。
例如:
/// 触发warning
var myVar: Int? = nil
myVar↓ ?? nil
var myVar: Int? = nil
myVar↓??nil
//不会触发warning
var myVar: Int?
myVar ?? 0
var myVar: Int? = nil
let langke = myVar
- 属性66 : object_literal 。对象字面量, swiftlint表示比起图片和颜色初始化,更喜欢对象字面量。因为swift初始化可以用表情,图片,颜色等,这不符合项目中的一些习惯用法。目前在terminal上使用swiftlint rules查看并没有这个属性。那自然现在在swift 3.0上测试并没有起到任何作用。但是这个属性推荐使用。
例如:
/// 官方给出的例子, 非触发warning
"let image = #imageLiteral(resourceName: \"image.jpg\")",
"let color = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)",
"let image = UIImage(named: aVariable)",
"let image = UIImage(named: \"interpolated \\(variable)\")",
"let color = UIColor(red: value, green: value, blue: value, alpha: 1)",
"let image = NSImage(named: aVariable)",
"let image = NSImage(named: \"interpolated \\(variable)\")",
"let color = NSColor(red: value, green: value, blue: value, alpha: 1)"
- 属性67 : private_unit_test 。私有的单元测试。被标记为private的单元测试不会被测试工具XCTest运行, 也就是说,被标记为private的单元测试会被静态跳过。
例如:
private ↓class FooTest: XCTestCase { ...............继承于测试用例类XCTestCase, 被标记为private,所以触发warning
func test1() {}
internal func test2() {}
public func test3() {}
private func test4() {}.......另外注意这里,上面既然不会通过,那显然这里也不会通过,根本不会走这个func
}
internal class FooTest: XCTestCase { ......开始通过测试,因为没有被标记为private
func test1() {}
internal func test2() {}
public func test3() {}
private ↓func test4() {}................不通过,因为被标记为private
}
public class FooTest: XCTestCase { ..........通过
func test1() {}
internal func test2() {}
public func test3() {}
private ↓func test4() {}.................不通过,因为被标记成private
}
class FooTest: XCTestCase { ..........通过
func test1() {}
internal func test2() {}
public func test3() {}
private ↓func test4() {}.................不通过,因为被标记成private
}
- 属性68 : frist_where 。直接看下面官方解释和示例, 这个属性没有测试。
例如:
description: "Prefer using `.first(where:)` over `.filter { }.first` in collections.",
nonTriggeringExamples: [
"kinds.filter(excludingKinds.contains).isEmpty && kinds.first == .identifier\n",
"myList.first(where: { $0 % 2 == 0 })\n",
"matchPattern(pattern).filter { $0.first == .identifier }\n"
],
triggeringExamples: [
"↓myList.filter { $0 % 2 == 0 }.first\n",
"↓myList.filter({ $0 % 2 == 0 }).first\n",
"↓myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first\n",
"↓myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first?.something()\n",
"↓myList.filter(someFunction).first\n"
]
- 属性69 : operator_whitespace 。空格/空白操作符。当定义空格操作符的时候,被定义的名字或类型两边应该各有一个单行空格操作符。推荐使用。
例如:
// 触发警告
class Something: Equatable {
var text: String?
// "=="和“(lhs: Something, rhs: Something)”之间应该有一个空格
static func ==(lhs: Something, rhs: Something) -> Bool {
return lhs.text == rhs.text
}
}
- 属性70 : overridden_super_call。一些复写方法应该总是调用父类
例如:
/// 这样会触发警告
class VCd: UIViewController {
override func viewWillAppear(_ animated: Bool) {
//没有调用父类
}
}
/// 不会触发警告
class VCd: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
}
持续更新中…..