Dynamic Inline

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
dynamic_inline lint 3.0.0

dynamic@inline(__alway)不要同时使用

示例

非触发

  1. class C {
  2. dynamic func f() {}}
  3. class C {
  4. @inline(__always) func f() {}}
  5. class C {
  6. @inline(never) dynamic func f() {}}

触发

  1. class C {
  2. @inline(__always) dynamic func f() {}
  3. }
  4. class C {
  5. @inline(__always) public dynamic func f() {}
  6. }
  7. class C {
  8. @inline(__always) dynamic internal func f() {}
  9. }
  10. class C {
  11. @inline(__always)
  12. dynamic func f() {}
  13. }
  14. class C {
  15. @inline(__always)
  16. dynamic
  17. func f() {}
  18. }

补充

深入理解Swift派发机制
Dynamic-Swift
@inline
内联函数


Empty Count

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
empty_count performance 3.0.0

判空首选isEmpty而不是count等于0

示例

非触发

  1. var count = 0
  2. [Int]().isEmpty
  3. [Int]().count > 1
  4. [Int]().count == 1
  5. [Int]().count == 0xff
  6. [Int]().count == 0b01
  7. [Int]().count == 0o07
  8. discount == 0
  9. order.discount == 0

触发

  1. [Int]().↓count == 0
  2. [Int]().↓count > 0
  3. [Int]().↓count != 0
  4. [Int]().↓count == 0x0
  5. [Int]().↓count == 0x00_00
  6. [Int]().↓count == 0b00
  7. [Int]().↓count == 0o00
  8. count == 0

Empty Enum Arguments

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
empty_enum_arguments style 3.0.0

当枚举和关联类型匹配并没被使用时,可以省略参数。

示例

非触发

  1. switch foo {
  2. case .bar: break
  3. }
  4. switch foo {
  5. case .bar(let x): break
  6. }
  7. switch foo {
  8. case let .bar(x): break
  9. }
  10. switch (foo, bar) {
  11. case (_, _): break
  12. }
  13. switch foo {
  14. case "bar".uppercased(): break
  15. }
  16. switch (foo, bar) {
  17. case (_, _) where !something: break
  18. }
  19. switch foo {
  20. case (let f as () -> String)?: break
  21. }
  22. switch foo {
  23. default: break
  24. }

触发

  1. switch foo {
  2. case .bar↓(_): break
  3. }
  4. switch foo {
  5. case .bar↓(): break
  6. }
  7. switch foo {
  8. case .bar↓(_), .bar2↓(_): break
  9. }
  10. switch foo {
  11. case .bar↓() where method() > 2: break
  12. }
  13. func example(foo: Foo) {
  14. switch foo {
  15. case case .bar↓(_):
  16. break
  17. }
  18. }

Empty Parameters

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
empty_parameters style 3.0.0

首选()->而不是Void->

示例

非触发

  1. let abc: () -> Void = {}
  2. func foo(completion: () -> Void)
  3. func foo(completion: () thows -> Void)
  4. let foo: (ConfigurationTests) -> Void throws -> Void)
  5. let foo: (ConfigurationTests) -> Void throws -> Void)
  6. let foo: (ConfigurationTests) ->Void throws -> Void)

触发

  1. let abc: ↓(Void) -> Void = {}
  2. func foo(completion: ↓(Void) -> Void)
  3. func foo(completion: ↓(Void) throws -> Void)
  4. let foo: ↓(Void) -> () throws -> Void)

Empty Parentheses with Trailing Closure

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
empty_parentheses_with_trailing_closure style 3.0.0

使用尾随闭包时,应当避免在方法调用后使用空括号

示例

非触发

  1. [1, 2].map { $0 + 1 }
  2. [1, 2].map({ $0 + 1 })
  3. [1, 2].reduce(0) { $0 + $1 }
  4. [1, 2].map { number in
  5. number + 1
  6. }
  7. let isEmpty = [1, 2].isEmpty()
  8. UIView.animateWithDuration(0.3, animations: {
  9. self.disableInteractionRightView.alpha = 0
  10. }, completion: { _ in
  11. ()
  12. })

触发

  1. [1, 2].map↓() { $0 + 1 }
  2. [1, 2].map↓( ) { $0 + 1 }
  3. [1, 2].map↓() { number in
  4. number + 1
  5. }
  6. [1, 2].map↓( ) { number in
  7. number + 1
  8. }
  9. func foo() -> [Int] {
  10. return [1, 2].map↓() { $0 + 1 }
  11. }

补充

为什么说是方法调用之后呢?
因为尾随闭包其实是调用方法的一个参数,但是可以写在外边,所以看起来反例里边的括号倒在闭包“之前”而非“之后”了。这里的之后指的是执行顺序而非书写顺序。


Empty String

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
empty_string performance 3.0.0

(判空)首选使用isEmpty而不是比较string和空字符串

示例

非触发

  1. myString.isEmpty
  2. !myString.isEmpy

触发

  1. myString == ""
  2. myString != ""

Empty XCTest Method

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
empty_xctest_method lint 3.0.0

避免使用空的测试方法

示例

非触发

  1. class TotoTests: XCTestCase {
  2. var foobar: Foobar?
  3. override func setUp() {
  4. super.setUp()
  5. foobar = Foobar()
  6. }
  7. override func tearDown() {
  8. foobar = nil
  9. super.tearDown()
  10. }
  11. func testFoo() {
  12. XCTAssertTrue(foobar?.foo)
  13. }
  14. func testBar() {
  15. // comment...
  16. XCTAssertFalse(foobar?.bar)
  17. // comment...
  18. }
  19. }
  20. class Foobar {
  21. func setUp() {}
  22. func tearDown() {}
  23. func testFoo() {}
  24. }
  25. class TotoTests: XCTestCase {
  26. func setUp(with object: Foobar) {}
  27. func tearDown(object: Foobar) {}
  28. func testFoo(_ foo: Foobar) {}
  29. func testBar(bar: (String) -> Int) {}
  30. }
  31. class TotoTests: XCTestCase {
  32. func testFoo() { XCTAssertTrue(foobar?.foo) }
  33. func testBar() { XCTAssertFalse(foobar?.bar) }
  34. }

触发

  1. class TotoTests: XCTestCase {
  2. override func setUp() {
  3. }
  4. override func tearDown() {
  5. }
  6. func testFoo() {
  7. }
  8. func testBar() {
  9. }
  10. func helperFunction() {
  11. }
  12. }
  13. class TotoTests: XCTestCase {
  14. override func setUp() {}
  15. override func tearDown() {}
  16. func testFoo() {}
  17. func helperFunction() {}
  18. }
  19. class TotoTests: XCTestCase {
  20. override func setUp() {
  21. // comment...
  22. }
  23. override func tearDown() {
  24. // comment...
  25. // comment...
  26. }
  27. func testFoo() {
  28. // comment...
  29. // comment...
  30. // comment...
  31. }
  32. func testBar() {
  33. /*
  34. * comment...
  35. *
  36. * comment...
  37. *
  38. * comment...
  39. */
  40. }
  41. func helperFunction() {
  42. }
  43. }
  44. class FooTests: XCTestCase {
  45. override func setUp() {}
  46. }
  47. class BarTests: XCTestCase {
  48. func testFoo() {}
  49. }

Explicit ACL

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
explicit_acl idiomatic 3.0.0

所有的声明都应该指定访问控制符。

示例

非触发

  1. internal enum A {}
  2. public final class B {}
  3. private struct C {}
  4. internal enum A {
  5. internal enum B {}
  6. }
  7. internal final class Foo {}
  8. internal
  9. class Foo { private let bar = 5 }
  10. internal func a() { let a = }
  11. private func a() { func innerFunction() { } }
  12. private enum Foo { enum Bar { } }
  13. private struct C { let d = 5 }
  14. internal protocol A {
  15. func b()
  16. }
  17. internal protocol A {
  18. var b: Int
  19. }
  20. internal class A { deinit {} }

触发

  1. enum A {}
  2. final class B {}
  3. internal struct C { let d = 5 }
  4. public struct C { let d = 5 }
  5. func a() {}
  6. internal let a = 0
  7. func b() {}

Explicit Enum Raw Value

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
explicit_enum_raw_value idiomatic 3.0.0

枚举类型最好指定明确的raw value

示例

非触发

  1. enum Numbers {
  2. case int(Int)
  3. case short(Int16)
  4. }
  5. enum Numbers: Int {
  6. case one = 1
  7. case two = 2
  8. }
  9. enum Numbers: Double {
  10. case one = 1.1
  11. case two = 2.2
  12. }
  13. enum Numbers: String {
  14. case one = "one"
  15. case two = "two"
  16. }
  17. protocol Algebra {}
  18. enum Numbers: Algebra {
  19. case one
  20. }

触发

  1. enum Numbers: Int {
  2. case one = 10, two, three = 30
  3. }
  4. enum Numbers: NSInteger {
  5. case one
  6. }
  7. enum Numbers: String {
  8. case one
  9. case two
  10. }
  11. enum Numbers: String {
  12. case one, two = "two"
  13. }
  14. enum Numbers: Decimal {
  15. case one, two
  16. }

Explicit Init

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
explicit init idiomatic 3.0.0

应当避免直接使用.init()

示例

非触发

  1. import Foundation;
  2. class C: NSObject {
  3. override init() {
  4. super.init()
  5. }
  6. }
  7. struct S {
  8. let n: Int
  9. };
  10. extension S {
  11. init() {
  12. self.init(n: 1)
  13. }
  14. }
  15. [1].flatMap(String.init)
  16. [String.self].map { $0.init(1) }
  17. [String.self].map { type in type.init(1) }

触发

  1. [1].flatMap{String↓.init($0)}
  2. [String.self].map { Type in Type↓.init(1) }
  3. func foo() -> [String] {
  4. return [1].flatMap { String↓.init($0) }
  5. }

Explicit Self

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
explicit self style style 3.0.0

应当使用self.调用自己的变量和方法

示例

非触发

  1. struct A {
  2. func f1() {}
  3. func f2() {
  4. self.f1()
  5. }
  6. }
  7. struct A {
  8. let p1: Int
  9. func f1() {
  10. _ = self.p1
  11. }
  12. }

触发

  1. struct A {
  2. func f1() {}
  3. func f2() {
  4. f1()
  5. }
  6. }
  7. struct A {
  8. let p1: Int
  9. func f1() {
  10. _ = p1
  11. }
  12. }

补充

持保留意见、我们总是喜欢短小,表达力强的代码。满屏的self并不是我喜欢的。


Explicit Top Level ACL

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
explicit_top_level_acl idiomatic 3.0.0

顶级声明必须明确指定访问权限控制符

示例

非触发

  1. internal enum A {}
  2. public final class B {}
  3. private struct C {}
  4. internal enum A {
  5. enum B {}
  6. }
  7. internal final class Foo {}
  8. internal
  9. class Foo {}
  10. internal func a() {}

触发

  1. enum A {}
  2. final class B {}
  3. struct C {}
  4. func a() {}
  5. internal let a = 0
  6. func b() {}

Explict Type Interface

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
explict type interface idiomatic 3.0.0

属性最好声明类型。

示例

非触发

  1. class Foo {
  2. var myVar: Int? = 0
  3. }
  4. class Foo {
  5. let myVar: Int? = 0
  6. }
  7. class Foo {
  8. static var myVar: Int? = 0
  9. }
  10. class Foo {
  11. class var myVar: Int? = 0
  12. }

触发

  1. class Foo {
  2. var myVar = 0
  3. }
  4. class Foo {
  5. let mylet = 0
  6. }
  7. class Foo {
  8. static var myStaticVar = 0
  9. }
  10. class Foo {
  11. class var myClassVar = 0
  12. }
  13. class Foo {
  14. let myVar = Int(0)
  15. }
  16. class Foo {
  17. let myVar = Set<Int>(0)
  18. }

Extension Access Modifier

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
extension_access_mofifier idiomatic 3.0.0

推荐使用扩展访问修饰符。

示例

非触发

  1. extension Foo: SomeProtocol {
  2. public var bar: Int { return 1 }
  3. }
  4. extension Foo {
  5. private var bar: Int { return 1 }
  6. public var baz: Int { return 1 }
  7. }
  8. extension Foo {
  9. private var bar: Int { return 1 }
  10. public func baz() {}
  11. }
  12. extension Foo {
  13. var bar: Int { return 1 }
  14. var baz: Int { return 1 }
  15. }
  16. public extension Foo {
  17. var bar: Int { return 1 }
  18. var baz: Int { return 1 }
  19. }
  20. extension Foo {
  21. private bar: Int { return 1 }
  22. private baz: Int { return 1 }
  23. }
  24. extension Foo {
  25. open bar: Int { return 1 }
  26. open baz: Int { return 1 }
  27. }

触发

  1. extension Foo {
  2. public var bar: Int { return 1 }
  3. public var baz: Int { return 1 }
  4. }
  5. extension Foo {
  6. public var bar: Int { return 1 }
  7. public func baz() {}
  8. }
  9. public extension Foo {
  10. public func bar() {}
  11. public func baz() {}
  12. }

补充

正例和反例有相同的地方、没能get到点子上。


Fallthrough

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
fallthrough idomatic 3.0.0

避免使用fallthough

示例

非触发

  1. switch foo {
  2. case .bar, .bar2, .bar3:
  3. something()
  4. }

触发

  1. switch foo {
  2. case .bar:
  3. fallthrough
  4. case .bar2:
  5. something()
  6. }

Fatal Error Message

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
fatal_error_message idiomatic 3.0.0

fatalError方法最好提供message

示例

非触发

  1. func foo() {
  2. fatalError("Foo")
  3. }
  4. func foo() {
  5. fatalError(x)
  6. }

触发

  1. func foo() {
  2. fatalError("")
  3. }
  4. func foo() {
  5. fatalError()
  6. }

补充

fatalError


File Header

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
file_header style 3.0.0

头部描述应当和项目模式一致。SWIFTLINT_CURRENT_FILENAME占位符可以配置必须和禁止选项,这将被真实的文件名替换。

示例

非触发

  1. let foo = "Copyright"
  2. let foo = 2 // Copyright
  3. let foo = 2
  4. // Copyright

触发

  1. // ↓Copyright
  2. //
  3. // ↓Copyright
  4. //
  5. // FileHeaderRule.swift
  6. // SwiftLint
  7. //
  8. // Created by Marcelo Fabri on 27/11/16.
  9. // ↓Copyright © 2016 Realm. All rights reserved.
  10. //

补充

我能想到的适用场景就是在文件重命名之后,相应的文件顶部的注释也要一并改掉。


File Line Length

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
file_length metrics 3.0.0

文件不要超过太多行

示例

非触发

  1. print("swiftlint")*400

触发

  1. print("swiftlint")*401

补充

查看源码可知建议不超过400行,个人感觉不好控制,业务复杂可以多一些,业务简单少一些。关键是模块划分合理,层次结构分明。不必过分追求代码行数。仁者见仁,智者见智。


File Name

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
file_name idiomatic 3.0.0

文件名应当和文件中声明的类型或扩展一致(若存在)


First Where

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
first_where performance 3.0.0

在集合对象中优先使用.first(where:)而不是.filter{}.first

示例

非触发

  1. kinds.filter(excludingKinds.contains).isEmpty && kinds.first == .identifier
  2. myList.first(where: { $0 % 2 == 0 })
  3. match(pattern: pattern).filter { $0.first == .identifier }
  4. (myList.filter { $0 == 1 }.suffix(2)).first

触发

  1. myList.filter { $0 % 2 == 0 }.first
  2. myList.filter({ $0 % 2 == 0 }).first
  3. myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first
  4. myList.map { $0 + 1 }.filter({ $0 % 2 == 0 }).first?.something()
  5. myList.filter(someFunction).first
  6. myList.filter({ $0 % 2 == 0 })
  7. .first
  8. (↓myList.filter { $0 == 1 }).first

For Where

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
for_where idiomatic 3.0.0

where修饰符优于在for中使用if

示例

非触发

  1. for user in users where user.id == 1 { }
  2. for user in users {
  3. if let id = user.id { }
  4. }
  5. for user in users {
  6. if var id = user.id { }
  7. }
  8. for user in users {
  9. if user.id == 1 { } else { }
  10. }
  11. for user in users {
  12. if user.id == 1 {
  13. } else if user.id == 2 { }
  14. }
  15. for user in users {
  16. if user.id == 1 { }
  17. print(user)
  18. }
  19. for user in users {
  20. let id = user.id
  21. if id == 1 { }
  22. }
  23. for user in users {
  24. if user.id == 1 { }
  25. return true
  26. }
  27. for user in users {
  28. if user.id == 1 && user.age > 18 { }
  29. }
  30. for (index, value) in array.enumerated() {
  31. if case .valueB(_) = value {
  32. return index
  33. }
  34. }

触发

  1. for user in users {
  2. if user.id == 1 { return true }
  3. }

Force Cast

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
force_cast idiomatic 3.0.0

应该避免强制转换

示例

非触发

  1. NSNumber() as? Int

触发

  1. NSNumber() as! Int

Force Try

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
force_try idiomatic 3.0.0

应该避免强制try

示例

非触发

  1. func a() throws {}; do { try a() } catch {}

触发

  1. func a() throws {}; try! a()

Force Unwrapping

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
force_unwrapping idiomatic 3.0.0

避免强制解包

示例

非触发

  1. if let url = NSURL(string: query)
  2. navigationController?.pushViewController(viewController, animated: true)
  3. let s as! Test
  4. try! canThrowErrors()
  5. let object: Any!
  6. @IBOutlet var constraints: [NSLayoutConstraint]!
  7. setEditing(!editing, animated: true)
  8. navigationController.setNavigationBarHidden(!navigationController.navigationBarHidden, animated: true)
  9. if addedToPlaylist && (!self.selectedFilters.isEmpty || self.searchBar?.text?.isEmpty == false) {}
  10. print("\(xVar)!")
  11. var test = (!bar)
  12. var a: [Int]!
  13. private var myProperty: (Void -> Void)!
  14. func foo(_ options: [AnyHashable: Any]!) {
  15. func foo() -> [Int]!
  16. func foo() -> [AnyHashable: Any]!
  17. func foo() -> [Int]! { return [] }

触发

  1. let url = NSURL(string: query)↓!
  2. navigationController↓!.pushViewController(viewController, animated: true)
  3. let unwrapped = optional↓!
  4. return cell↓!
  5. let url = NSURL(string: "http://www.google.com")↓!
  6. let dict = ["Boooo": "👻"]func bla() -> String { return dict["Boooo"]↓! }
  7. let dict = ["Boooo": "👻"]func bla() -> String { return dict["Boooo"]↓!.contains("B") }
  8. let a = dict["abc"]↓!.contains("B")
  9. dict["abc"]↓!.bar("B")
  10. if dict["a"]↓!!!! {
  11. var foo: [Bool]! = dict["abc"]↓!
  12. context("abc") {
  13. var foo: [Bool]! = dict["abc"]↓!
  14. }
  15. open var computed: String { return foo.bar↓! }

Function Body Length

标识符 默认开启 支持自动更正 类别 分析仪 最低swift编译版本
function_body_length metrics 3.0.0

函数主体不要过长