AnyObject Protocol
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
| AnyObject Protocol |
否 |
是 |
lint |
否 |
4.1.0 |
对于class-only protocols 优先使用AnyObject而不是Class
示例
非触发
protocol SomeProtocol {}protocol SomeClassOnlyProtocol: AnyObject {}protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {}@objc protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {}
触发
protocol SomeClassOnlyProtocol: ↓class {}protocol SomeClassOnlyProtocol: ↓class, SomeInheritedProtocol {}@objc protocol SomeClassOnlyProtocol: ↓class, SomeInheritedProtocol {}
补充
定义委托时,我们让 protocol 继承自 AnyObject。这是由于,在 Swift 中,这表示这一个协议只能被应用于 class(而不是 struct 和 enum)。
实际上,如果让 protocol 不继承自任何东西,那也是可以的,这样定义的 Delegate 就可以被应用于 class 以及 struct、enum。由于 Delegate 代表的是遵循了该协议的实例,所以当 Delegate 被应用于 class 时,它就是 Reference type,需要考虑循环引用的问题,因此就必须要用 weak 关键字。
但是这样的问题在于,当 Delegate 被应用于 struct 和 enum 时,它是 Value type,不需要考虑循环引用的问题,也不能被使用 weak 关键字。所以当 Delegate 未限定只能用于 class,Xcode 就会对 weak 关键字报错:‘weak’ may only be applied to class and class-bound protocol types
那么为什么不使用 class 和 NSObjectProtocol,而要使用 AnyObject 呢?NSObjectProtocol 来自 Objective-C,在 pure Swift 的项目中并不推荐使用。class 和 AnyObject 并没有什么区别,在 Xcode 中也能达到相同的功能,但是官方还是推荐使用 AnyObject。
来源 wift Protocol 详解 - 协议&面向协议编程
Array Init
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
| Array Init |
否 |
否 |
lint |
否 |
3.0.0 |
将序列(sequence)转化为数组 优先使用Array(seq) 而不是 seq.map{$0}
示例
非触发
Array(foo)foo.map { $0.0 }foo.map { $1 }foo.map { $0() }foo.map { ((), $0) }foo.map { $0! }foo.map { $0! /* force unwrap */ }foo.something { RouteMapper.map($0) }
触发
↓foo.map({ $0 })↓foo.map { $0 }↓foo.map { return $0 }↓foo.map { elem in elem}↓foo.map { elem in return elem}↓foo.map { (elem: String) in elem}↓foo.map { elem -> String in elem}↓foo.map { $0 /* a comment */ }
Attributes
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
| Attributes |
否 |
否 |
style |
否 |
3.0.0 |
属性修饰符在修饰类型和函数时需要单独一行,但在修饰变量和引入时须写在同一行
示例
非触发
@objc var x: String@objc private var x: String@nonobjc var x: String@IBOutlet private var label: UILabel@IBOutlet @objc private var label: UILabel@NSCopying var name: NSString@NSManaged var name: String?@IBInspectable var cornerRadius: CGFloat@available(iOS 9.0, *) let stackView: UIStackView@NSManaged func addSomeObject(book: SomeObject)@IBAction func buttonPressed(button: UIButton)@objc @IBAction func buttonPressed(button: UIButton)@available(iOS 9.0, *) func animate(view: UIStackView)@available(iOS 9.0, *, message="A message") func animate(view: UIStackView)@nonobjc final class X@available(iOS 9.0, *) class UIStackView@NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate@UIApplicationMain class AppDelegate: NSObject, UIApplicationDelegate@IBDesignable class MyCustomView: UIView@testable import SourceKittenFramework@objc(foo_x) var x: String@available(iOS 9.0, *)@objc(abc_stackView) let stackView: UIStackView@objc(abc_addSomeObject:) @NSManaged func addSomeObject(book: SomeObject)@objc(ABCThing) @available(iOS 9.0, *) class Thingclass Foo: NSObject { override var description: String { return "" }}class Foo: NSObject { override func setUp() {}}@objcclass ⽺ {}extension Property { @available(*, unavailable, renamed: "isOptional")public var optional: Bool { fatalError() }}@GKInspectable var maxSpeed: Float@discardableResult func a() -> Int@objc @discardableResult func a() -> Intfunc increase(f: @autoclosure () -> Int) -> Intfunc foo(completionHandler: @escaping () -> Void)private struct DefaultError: Error {}@testable import fooprivate let bar = 1import XCTest@testable import DeleteMe@available (iOS 11.0, *)class DeleteMeTests: XCTestCase {}
触发
@objc ↓var x: String@objc ↓var x: String@objc private ↓var x: String@nonobjc ↓var x: String@IBOutlet private ↓var label: UILabel@IBOutlet private ↓var label: UILabel@NSCopying ↓var name: NSString@NSManaged ↓var name: String?@IBInspectable ↓var cornerRadius: CGFloat@available(iOS 9.0, *) ↓let stackView: UIStackView@NSManaged ↓func addSomeObject(book: SomeObject)@IBAction ↓func buttonPressed(button: UIButton)@IBAction @objc ↓func buttonPressed(button: UIButton)@available(iOS 9.0, *) ↓func animate(view: UIStackView)@nonobjc final ↓class X@available(iOS 9.0, *) ↓class UIStackView@available(iOS 9.0, *) @objc ↓class UIStackView@available(iOS 9.0, *) @objc ↓class UIStackView@available(iOS 9.0, *) ↓class UIStackView@UIApplicationMain ↓class AppDelegate: NSObject, UIApplicationDelegate@IBDesignable ↓class MyCustomView: UIView@testable↓import SourceKittenFramework@testable↓import SourceKittenFramework@objc(foo_x) ↓var x: String@available(iOS 9.0, *) @objc(abc_stackView) ↓let stackView: UIStackView@objc(abc_addSomeObject:) @NSManaged ↓func addSomeObject(book: SomeObject)@objc(abc_addSomeObject:) @NSManaged ↓func addSomeObject(book: SomeObject)@available(iOS 9.0, *) @objc(ABCThing) ↓class Thing@GKInspectable ↓var maxSpeed: Float@discardableResult ↓func a() -> Int@objc @discardableResult ↓func a() -> Int@objc @discardableResult ↓func a() -> Int
Block Based KVO
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
block_based_kvo |
是 |
否 |
idiomatic |
否 |
3.0.0 |
Swift3.2只后 最好使用block的方式来调用KVO的API
示例
非触发
let observer = foo.observe(\.value, options: [.new]) { (foo, change) in print(change.newValue)}
触发
class Foo: NSObject { override ↓func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {}}class Foo: NSObject { override ↓func observeValue(forKeyPath keyPath: String?, of object: Any?, change: Dictionary<NSKeyValueChangeKey, Any>?, context: UnsafeMutableRawPointer?) {}}
Class Delegate Protocol
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
class_delegate_protocol |
是 |
否 |
lint |
否 |
3.0.0 |
代理模式的delegate只能用于class,这样才可以被置弱引用。
示例
非触发
protocol FooDelegate: class {}protocol FooDelegate: class, BarDelegate {}protocol Foo {}class FooDelegate {}@objc protocol FooDelegate {}@objc(MyFooDelegate)protocol FooDelegate {}protocol FooDelegate: BarDelegate {}protocol FooDelegate: AnyObject {}protocol FooDelegate: NSObjectProtocol {}
触发
↓protocol FooDelegate {}↓protocol FooDelegate: Bar {}
Closing Brace Spacing
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
closing_brace |
是 |
是 |
style |
否 |
3.0.0 |
闭合括号和内容之间不应该存在空格
示例
非触发
[].map({ })[].map( { })
触发
[].map({ ↓} )[].map({ ↓} )
Closure Body Length
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
closure_body_length |
否 |
否 |
metrics |
否 |
4.2.0 |
闭包不应该过长
示例
非触发
foo.bar { $0 }foo.bar { toto in}foo.bar { toto in let a = 0 // toto // toto // toto // toto // toto // toto // toto // toto // toto // toto}foo.bar { toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0}foo.bar { toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 // toto // toto // toto // toto // toto // toto // toto // toto // toto // toto}foo.bar({ toto in})foo.bar({ toto in let a = 0})foo.bar({ toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0})foo.bar(label: { toto in})foo.bar(label: { toto in let a = 0})foo.bar(label: { toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0})foo.bar(label: { toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0}, anotherLabel: { toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0})foo.bar(label: { toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0}) { toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0}let foo: Bar = { toto in let bar = Bar() let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 return bar}()
触发
foo.bar ↓{ toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0}foo.bar ↓{ toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 // toto // toto // toto // toto // toto // toto // toto // toto // toto // toto}foo.bar(↓{ toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0})foo.bar(label: ↓{ toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0})foo.bar(label: ↓{ toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0}, anotherLabel: ↓{ toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0})foo.bar(label: ↓{ toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0}) ↓{ toto in let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0}let foo: Bar = ↓{ toto in let bar = Bar() let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 let a = 0 return bar}()
补充
感觉这个示例有点看不懂 为何非触发里边也可以写那么长。。。
Closure End Indentation
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
closure_end_indentation |
否 |
是 |
style |
否 |
3.0.0 |
闭包的结尾应该和它的调用有同样的缩进
示例
非触发
SignalProducer(values: [1, 2, 3]) .startWithNext { number in print(number) }[1, 2].map { $0 + 1 }return match(pattern: pattern, with: [.comment]).flatMap { range in return Command(string: contents, range: range)}.flatMap { command in return command.expand()}foo(foo: bar, options: baz) { _ in }someReallyLongProperty.chainingWithAnotherProperty .foo { _ in }foo(abc, 123){ _ in }function( closure: { x in print(x) }, anotherClosure: { y in print(y) })function(parameter: param, closure: { x in print(x)})function(parameter: param, closure: { x in print(x) }, anotherClosure: { y in print(y) })
触发
SignalProducer(values: [1, 2, 3]) .startWithNext { number in print(number)↓}return match(pattern: pattern, with: [.comment]).flatMap { range in return Command(string: contents, range: range) ↓}.flatMap { command in return command.expand()↓}function( closure: { x in print(x)↓}, anotherClosure: { y in print(y)↓})
Closure Parameter Position
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
closure_parameter_position |
是 |
否 |
style |
否 |
3.0.0 |
闭包参数应该和左括号在同一行
示例
非触发
[1, 2].map { $0 + 1 }[1, 2].map({ $0 + 1 })[1, 2].map { number in number + 1 }[1, 2].map { number -> Int in number + 1 }[1, 2].map { (number: Int) -> Int in number + 1 }[1, 2].map { [weak self] number in number + 1 }[1, 2].something(closure: { number in number + 1 })let isEmpty = [1, 2].isEmpty()rlmConfiguration.migrationBlock.map { rlmMigration inreturn { migration, schemaVersion inrlmMigration(migration.rlmMigration, schemaVersion)}}let mediaView: UIView = { [weak self] index in return UIView()}(index)
触发
[1, 2].map { ↓number in number + 1 }[1, 2].map { ↓number -> Int in number + 1 }[1, 2].map { (↓number: Int) -> Int in number + 1 }[1, 2].map { [weak self] ↓number in number + 1 }[1, 2].map { [weak self] ↓number in number + 1 }[1, 2].map({ ↓number in number + 1 })[1, 2].something(closure: { ↓number in number + 1 })[1, 2].reduce(0) { ↓sum, ↓number in number + sum }
Closure Spacing
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
closure_spacing |
否 |
是 |
style |
否 |
3.0.0 |
闭包表达式应该与前后括号之间有一个空格
示例
非触发
[].map ({ $0.description })[].filter { $0.contains(location) }extension UITableViewCell: ReusableView { }extension UITableViewCell: ReusableView {}
触发
[].filter(↓{$0.contains(location)})[].map(↓{$0})(↓{each in return result.contains(where: ↓{e in return e}) }).countfilter ↓{ sorted ↓{ $0 < $1}}
Collection Element Alignment
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
collection_alignment |
否 |
否 |
style |
否 |
3.0.0 |
集合中的所有元素都应该垂直对齐。
示例
非触发
doThings(arg: [ "foo": 1, "bar": 2, "fizz": 2, "buzz": 2])let abc = [ "alpha": "a", "beta": "b", "gamma": "g", "delta": "d", "epsilon": "e"]let meals = [ "breakfast": "oatmeal", "lunch": "sandwich", "dinner": "burger"]let coordinates = [ CLLocationCoordinate2D(latitude: 0, longitude: 33), CLLocationCoordinate2D(latitude: 0, longitude: 66), CLLocationCoordinate2D(latitude: 0, longitude: 99)]var evenNumbers: Set<Int> = [ 2, 4, 6]let abc = [1, 2, 3, 4]let abc = [ 1, 2, 3, 4]let abc = [ "foo": "bar", "fizz": "buzz"]var evenNumbers: Set<Int> = [ 2, 4, 6]let abc = [1, 2, 3, 4]let abc = [ 1, 2, 3, 4]let abc = [ "foo": "bar", "fizz": "buzz"]
触发
doThings(arg: [ "foo": 1, "bar": 2, ↓"fizz": 2, ↓"buzz": 2])let abc = [ "alpha": "a", ↓"beta": "b", "gamma": "g", "delta": "d", ↓"epsilon": "e"]let meals = [ "breakfast": "oatmeal", "lunch": "sandwich", ↓"dinner": "burger"]let coordinates = [ CLLocationCoordinate2D(latitude: 0, longitude: 33), ↓CLLocationCoordinate2D(latitude: 0, longitude: 66), CLLocationCoordinate2D(latitude: 0, longitude: 99)]var evenNumbers: Set<Int> = [ 2, ↓4, 6]
Colon
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
colon |
是 |
是 |
style |
否 |
3.0.0 |
声明类型时,冒号应该紧邻标识符;字典中应与key紧邻。
示例
非触发
let abc: Voidlet abc: [Void: Void]let abc: (Void, Void)let abc: ([Void], String, Int)let abc: [([Void], String, Int)]let abc: String="def"let abc: Int=0let abc: Enum=Enum.Valuefunc abc(def: Void) {}func abc(def: Void, ghi: Void) {}let abc: String = "abc:"let abc = [Void: Void]()let abc = [1: [3: 2], 3: 4]let abc = ["string": "string"]let abc = ["string:string": "string"]let abc: [String: Int]func foo(bar: [String: Int]) {}func foo() -> [String: Int] { return [:] }let abc: Anylet abc: [Any: Int]let abc: [String: Any]class Foo: Bar {}class Foo<T: Equatable> {}switch foo {case .bar: _ = something()}object.method(x: 5, y: "string")object.method(x: 5, y: "string")object.method(5, y: "string")func abc() { def(ghi: jkl) }func abc(def: Void) { ghi(jkl: mno) }class ABC { let def = ghi(jkl: mno) } }func foo() { let dict = [1: 1] }
触发
let ↓abc:Voidlet ↓abc: Voidlet ↓abc :Voidlet ↓abc : Voidlet ↓abc : [Void: Void]let ↓abc : (Void, String, Int)let ↓abc : ([Void], String, Int)let ↓abc : [([Void], String, Int)]let ↓abc: (Void, String, Int)let ↓abc: ([Void], String, Int)let ↓abc: [([Void], String, Int)]let ↓abc :String="def"let ↓abc :Int=0let ↓abc :Int = 0let ↓abc:Int=0let ↓abc:Int = 0let ↓abc:Enum=Enum.Valuefunc abc(↓def:Void) {}func abc(↓def: Void) {}func abc(↓def :Void) {}func abc(↓def : Void) {}func abc(def: Void, ↓ghi :Void) {}let abc = [Void↓:Void]()let abc = [Void↓ : Void]()let abc = [Void↓: Void]()let abc = [Void↓ : Void]()let abc = [1: [3↓ : 2], 3: 4]let abc = [1: [3↓ : 2], 3↓: 4]let abc: [↓String : Int]let abc: [↓String:Int]func foo(bar: [↓String : Int]) {}func foo(bar: [↓String:Int]) {}func foo() -> [↓String : Int] { return [:] }func foo() -> [↓String:Int] { return [:] }let ↓abc : Anylet abc: [↓Any : Int]let abc: [↓String : Any]class ↓Foo : Bar {}class ↓Foo:Bar {}class Foo<↓T:Equatable> {}class Foo<↓T : Equatable> {}object.method(x: 5, y↓ : "string")object.method(x↓:5, y: "string")object.method(x↓: 5, y: "string")func abc() { def(ghi↓:jkl) }func abc(def: Void) { ghi(jkl↓:mno) }class ABC { let def = ghi(jkl↓:mno) } }func foo() { let dict = [1↓ : 1] }
Comma Spacing
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
comma |
是 |
是 |
style |
否 |
3.0.0 |
任何逗号前边都不应该有空格。
示例
非触发
func abc(a: String, b: String) { }abc(a: "string", b: "string"enum a { case a, b, c }func abc( a: String, // comment bcd: String // comment) {}func abc( a: String, bcd: String) {}#imageLiteral(resourceName: "foo,bar,baz")
触发
func abc(a: String↓ ,b: String) { }func abc(a: String↓ ,b: String↓ ,c: String↓ ,d: String) { }abc(a: "string"↓,b: "string"enum a { case a↓ ,b }let result = plus( first: 3↓ , // #683 second: 4)
Compiler Protocol Init
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
compiler_protocol_init |
是 |
否 |
lint |
否 |
3.0.0 |
遵循例如ExpressibleByArrayLiteral协议的初始化方法不应当被调用
示例
非触发
let set: Set<Int> = [1, 2]let set = Set(array)
触发
let set = ↓Set(arrayLiteral: 1, 2)let set = ↓Set.init(arrayLiteral: 1, 2)
补充
这一点苹果的文档已经加以说明了 该方法是给编译器使用的,我们初始化应该采用逗号的这种形式。
/// Do not call this initializer directly. It is used by the compiler when/// you use an array literal. Instead, create a new set using an array/// literal as its value by enclosing a comma ...public init(arrayLiteral elements: Set.Element...)
Conditional Returns on Newline
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
conditional_returns_on_newline |
否 |
否 |
style |
否 |
3.0.0 |
条件表达式的返回值需要另起一行。
示例
非触发
guard true else { return true}guard true, let x = true else { return true}if true else { return true}if true, let x = true else { return true}if textField.returnKeyType == .Next {if true { // return }/*if true { */ return }
触发
↓guard true else { return }↓if true { return }↓if true { break } else { return }↓if true { break } else { return }↓if true { return "YES" } else { return "NO" }
Contains over first not nil
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
contains_over_first_not_nil |
否 |
否 |
performance |
否 |
3.0.0 |
contains优于first(where:) != nil
示例
非触发
let first = myList.first(where: { $0 % 2 == 0 })let first = myList.first { $0 % 2 == 0 }
触发
↓myList.first { $0 % 2 == 0 } != nil↓myList.first(where: { $0 % 2 == 0 }) != nil↓myList.map { $0 + 1 }.first(where: { $0 % 2 == 0 }) != nil↓myList.first(where: someFunction) != nil↓myList.map { $0 + 1 }.first { $0 % 2 == 0 } != nil(↓myList.first { $0 % 2 == 0 }) != nil
Control Statement
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
control_statement |
是 |
否 |
style |
否 |
3.0.0 |
if, for, guard, switch, while, catch关键字的条件、参数没必要用括号括起来。
示例
非触发
if condition {if (a, b) == (0, 1) {if (a || b) && (c || d) {if (min...max).contains(value) {if renderGif(data) {renderGif(data)for item in collection {for (key, value) in dictionary {for (index, value) in enumerate(array) {for var index = 0; index < 42; index++ {guard condition else {while condition {} while condition {do { ; } while condition {switch foo {do {} catch let error as NSError {}foo().catch(all: true) {}if max(a, b) < c {switch (lhs, rhs) {
触发
↓if (condition) {↓if(condition) {↓if (condition == endIndex) {↓if ((a || b) && (c || d)) {↓if ((min...max).contains(value)) {↓for (item in collection) {↓for (var index = 0; index < 42; index++) {↓for(item in collection) {↓for(var index = 0; index < 42; index++) {↓guard (condition) else {↓while (condition) {↓while(condition) {} ↓while (condition) {} ↓while(condition) {do { ; } ↓while(condition) {do { ; } ↓while (condition) {↓switch (foo) {do {} ↓catch(let error as NSError) {}↓if (max(a, b) < c) {
Convenience Type
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
convenience_type |
否 |
否 |
idiomatic |
否 |
4.1.0 |
只用于存储静态成员的类型应该使用无壳的enum以避免初始化。
示例
非触发
enum Math { // enum public static let pi = 3.14}// class with inheritanceclass MathViewController: UIViewController { public static let pi = 3.14}@objc class Math: NSObject { // class visible to Obj-C public static let pi = 3.14}struct Math { // type with non-static declarations public static let pi = 3.14 public let randomNumber = 2}class DummyClass {}
触发
↓struct Math { public static let pi = 3.14}↓class Math { public static let pi = 3.14}↓struct Math { public static let pi = 3.14 @available(*, unavailable) init() {}}
Custom Rules
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
custom_rules |
时 |
否 |
Style |
No |
3.0.0 |
通过正则表达式来创建自定义规则。
(可选)指定要匹配的语法类型,严重程度和提示信息。
Cyclomatic Complexity
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
cyclomatic_complexity |
是 |
否 |
metrics |
否 |
3.0.0 |
应该控制函数的复杂度。
示例
非触发
func f1() {if true {for _ in 1..5 { } }if false { }}func f(code: Int) -> Int {switch code { case 0: fallthroughcase 0: return 1case 0: return 1case 0: return 1case 0: return 1case 0: return 1case 0: return 1case 0: return 1case 0: return 1default: return 1}}func f1() {if true {}; if true {}; if true {}; if true {}; if true {}; if true {}func f2() {if true {}; if true {}; if true {}; if true {}; if true {}}}
触发
↓func f1() { if true { if true { if false {} } } if false {} let i = 0 switch i { case 1: break case 2: break case 3: break case 4: break default: break } for _ in 1...5 { guard true else { return } }}
Discarded Notification Center Observer
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
discarded_notification_center_observer |
是 |
否 |
lint |
否 |
3.0.0 |
当使用block注册观察者时, 不可见的观察者应当被返回并存储,以便后续移除。
示例
非触发
let foo = nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil) { }let foo = nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { })func foo() -> Any { return nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { })}
触发
↓nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil) { }↓nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { })@discardableResult func foo() -> Any { return ↓nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { })}
Discouraged Direct Initialization
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
discouraged_direact_initialization |
是 |
否 |
lint |
否 |
3.0.0 |
不推荐直接初始化有副作用的类型。
示例
非触发
let foo = UIDevice.currentlet foo = Bundle.mainlet foo = Bundle(path: "bar")let foo = Bundle(identifier: "bar")let foo = Bundle.init(path: "bar")let foo = Bundle.init(identifier: "bar")
触发
↓UIDevice()↓Bundle()let foo = ↓UIDevice()let foo = ↓Bundle()let foo = bar(bundle: ↓Bundle(), device: ↓UIDevice())↓UIDevice.init()↓Bundle.init()let foo = ↓UIDevice.init()let foo = ↓Bundle.init()let foo = bar(bundle: ↓Bundle.init(), device: ↓UIDevice.init())
Discouraged Object Literal
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
discouraged_object_literal |
否 |
否 |
idiomatic |
否 |
3.0.0 |
首选初始化赋值,不推荐使用Object Literal。
示例
非触发
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)
触发
let image = ↓#imageLiteral(resourceName: "image.jpg")let color = ↓#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
补充
swift-literal
Discouraged Optional Boolean
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
discouraged_optional_boolean |
否 |
否 |
idiomatic |
否 |
3.0.0 |
首选使用非可选的布尔类型。
示例
非触发
var foo: Boolvar foo: [String: Bool]var foo: [Bool]let foo: Bool = truelet foo: Bool = falselet foo: [String: Bool] = [:]let foo: [Bool] = []var foo: Bool { return true }let foo: Bool { return false }()func foo() -> Bool {}func foo() -> [String: Bool] {}func foo() -> ([Bool]) -> String {}func foo(input: Bool = true) {}func foo(input: [String: Bool] = [:]) {}func foo(input: [Bool] = []) {}class Foo { func foo() -> Bool {}}class Foo { func foo() -> [String: Bool] {}}class Foo { func foo() -> ([Bool]) -> String {}}struct Foo { func foo() -> Bool {}}struct Foo { func foo() -> [String: Bool] {}}struct Foo { func foo() -> ([Bool]) -> String {}}enum Foo { func foo() -> Bool {}}enum Foo { func foo() -> [String: Bool] {}}enum Foo { func foo() -> ([Bool]) -> String {}}class Foo { func foo(input: Bool = true) {}}class Foo { func foo(input: [String: Bool] = [:]) {}}class Foo { func foo(input: [Bool] = []) {}}struct Foo { func foo(input: Bool = true) {}}struct Foo { func foo(input: [String: Bool] = [:]) {}}struct Foo { func foo(input: [Bool] = []) {}}enum Foo { func foo(input: Bool = true) {}}enum Foo { func foo(input: [String: Bool] = [:]) {}}enum Foo { func foo(input: [Bool] = []) {}}
触发
var foo: ↓Bool?var foo: [String: ↓Bool?]var foo: [↓Bool?]let foo: ↓Bool? = nillet foo: [String: ↓Bool?] = [:]let foo: [↓Bool?] = []let foo = ↓Optional.some(false)let foo = ↓Optional.some(true)var foo: ↓Bool? { return nil }let foo: ↓Bool? { return nil }()func foo() -> ↓Bool? {}func foo() -> [String: ↓Bool?] {}func foo() -> [↓Bool?] {}static func foo() -> ↓Bool? {}static func foo() -> [String: ↓Bool?] {}static func foo() -> [↓Bool?] {}func foo() -> (↓Bool?) -> String {}func foo() -> ([Int]) -> ↓Bool? {}func foo(input: ↓Bool?) {}func foo(input: [String: ↓Bool?]) {}func foo(input: [↓Bool?]) {}static func foo(input: ↓Bool?) {}static func foo(input: [String: ↓Bool?]) {}static func foo(input: [↓Bool?]) {}class Foo { var foo: ↓Bool?}class Foo { var foo: [String: ↓Bool?]}class Foo { let foo: ↓Bool? = nil}class Foo { let foo: [String: ↓Bool?] = [:]}class Foo { let foo: [↓Bool?] = []}struct Foo { var foo: ↓Bool?}struct Foo { var foo: [String: ↓Bool?]}struct Foo { let foo: ↓Bool? = nil}struct Foo { let foo: [String: ↓Bool?] = [:]}struct Foo { let foo: [↓Bool?] = []}class Foo { var foo: ↓Bool? { return nil }}class Foo { let foo: ↓Bool? { return nil }()}struct Foo { var foo: ↓Bool? { return nil }}struct Foo { let foo: ↓Bool? { return nil }()}enum Foo { var foo: ↓Bool? { return nil }}enum Foo { let foo: ↓Bool? { return nil }()}class Foo { func foo() -> ↓Bool? {}}class Foo { func foo() -> [String: ↓Bool?] {}}class Foo { func foo() -> [↓Bool?] {}}class Foo { static func foo() -> ↓Bool? {}}class Foo { static func foo() -> [String: ↓Bool?] {}}class Foo { static func foo() -> [↓Bool?] {}}class Foo { func foo() -> (↓Bool?) -> String {}}class Foo { func foo() -> ([Int]) -> ↓Bool? {}}struct Foo { func foo() -> ↓Bool? {}}struct Foo { func foo() -> [String: ↓Bool?] {}}struct Foo { func foo() -> [↓Bool?] {}}struct Foo { static func foo() -> ↓Bool? {}}struct Foo { static func foo() -> [String: ↓Bool?] {}}struct Foo { static func foo() -> [↓Bool?] {}}struct Foo { func foo() -> (↓Bool?) -> String {}}struct Foo { func foo() -> ([Int]) -> ↓Bool? {}}enum Foo { func foo() -> ↓Bool? {}}enum Foo { func foo() -> [String: ↓Bool?] {}}enum Foo { func foo() -> [↓Bool?] {}}enum Foo { static func foo() -> ↓Bool? {}}enum Foo { static func foo() -> [String: ↓Bool?] {}}enum Foo { static func foo() -> [↓Bool?] {}}enum Foo { func foo() -> (↓Bool?) -> String {}}enum Foo { func foo() -> ([Int]) -> ↓Bool? {}}class Foo { func foo(input: ↓Bool?) {}}class Foo { func foo(input: [String: ↓Bool?]) {}}class Foo { func foo(input: [↓Bool?]) {}}class Foo { static func foo(input: ↓Bool?) {}}class Foo { static func foo(input: [String: ↓Bool?]) {}}class Foo { static func foo(input: [↓Bool?]) {}}struct Foo { func foo(input: ↓Bool?) {}}struct Foo { func foo(input: [String: ↓Bool?]) {}}struct Foo { func foo(input: [↓Bool?]) {}}struct Foo { static func foo(input: ↓Bool?) {}}struct Foo { static func foo(input: [String: ↓Bool?]) {}}struct Foo { static func foo(input: [↓Bool?]) {}}enum Foo { func foo(input: ↓Bool?) {}}enum Foo { func foo(input: [String: ↓Bool?]) {}}enum Foo { func foo(input: [↓Bool?]) {}}enum Foo { static func foo(input: ↓Bool?) {}}enum Foo { static func foo(input: [String: ↓Bool?]) {}}enum Foo { static func foo(input: [↓Bool?]) {}}
Discouraged Optional Collection
| 标识符 |
默认开启 |
支持自动更正 |
类别 |
分析仪 |
最低swift编译版本 |
discouraged_optional_collection |
是 |
否 |
lint |
否 |
3.0.0 |
首选使用非可选的Collection
示例
非触发
var foo: [Int]var foo: [String: Int]var foo: Set<String>var foo: [String: [String: Int]]let foo: [Int] = []let foo: [String: Int] = [:]let foo: Set<String> = []let foo: [String: [String: Int]] = [:]var foo: [Int] { return [] }func foo() -> [Int] {}func foo() -> [String: String] {}func foo() -> Set<Int> {}func foo() -> ([Int]) -> String {}func foo(input: [String] = []) {}func foo(input: [String: String] = [:]) {}func foo(input: Set<String> = []) {}class Foo { func foo() -> [Int] {}}class Foo { func foo() -> [String: String] {}}class Foo { func foo() -> Set<Int> {}}class Foo { func foo() -> ([Int]) -> String {}}struct Foo { func foo() -> [Int] {}}struct Foo { func foo() -> [String: String] {}}struct Foo { func foo() -> Set<Int> {}}struct Foo { func foo() -> ([Int]) -> String {}}enum Foo { func foo() -> [Int] {}}enum Foo { func foo() -> [String: String] {}}enum Foo { func foo() -> Set<Int> {}}enum Foo { func foo() -> ([Int]) -> String {}}class Foo { func foo(input: [String] = []) {}}class Foo { func foo(input: [String: String] = [:]) {}}class Foo { func foo(input: Set<String> = []) {}}struct Foo { func foo(input: [String] = []) {}}struct Foo { func foo(input: [String: String] = [:]) {}}struct Foo { func foo(input: Set<String> = []) {}}enum Foo { func foo(input: [String] = []) {}}enum Foo { func foo(input: [String: String] = [:]) {}}enum Foo { func foo(input: Set<String> = []) {}}
触发
↓var foo: [Int]?↓var foo: [String: Int]?↓var foo: Set<String>?↓let foo: [Int]? = nil↓let foo: [String: Int]? = nil↓let foo: Set<String>? = nil↓var foo: [Int]? { return nil }↓let foo: [Int]? { return nil }()func ↓foo() -> [T]? {}func ↓foo() -> [String: String]? {}func ↓foo() -> [String: [String: String]]? {}func ↓foo() -> [String: [String: String]?] {}func ↓foo() -> Set<Int>? {}static func ↓foo() -> [T]? {}static func ↓foo() -> [String: String]? {}static func ↓foo() -> [String: [String: String]]? {}static func ↓foo() -> [String: [String: String]?] {}static func ↓foo() -> Set<Int>? {}func ↓foo() -> ([Int]?) -> String {}func ↓foo() -> ([Int]) -> [String]? {}func foo(↓input: [String: String]?) {}func foo(↓input: [String: [String: String]]?) {}func foo(↓input: [String: [String: String]?]) {}func foo(↓↓input: [String: [String: String]?]?) {}func foo<K, V>(_ dict1: [K: V], ↓_ dict2: [K: V]?) -> [K: V]func foo<K, V>(dict1: [K: V], ↓dict2: [K: V]?) -> [K: V]static func foo(↓input: [String: String]?) {}static func foo(↓input: [String: [String: String]]?) {}static func foo(↓input: [String: [String: String]?]) {}static func foo(↓↓input: [String: [String: String]?]?) {}static func foo<K, V>(_ dict1: [K: V], ↓_ dict2: [K: V]?) -> [K: V]static func foo<K, V>(dict1: [K: V], ↓dict2: [K: V]?) -> [K: V]class Foo { ↓var foo: [Int]?}class Foo { ↓var foo: [String: Int]?}class Foo { ↓var foo: Set<String>?}class Foo { ↓let foo: [Int]? = nil}class Foo { ↓let foo: [String: Int]? = nil}class Foo { ↓let foo: Set<String>? = nil}struct Foo { ↓var foo: [Int]?}struct Foo { ↓var foo: [String: Int]?}struct Foo { ↓var foo: Set<String>?}struct Foo { ↓let foo: [Int]? = nil}struct Foo { ↓let foo: [String: Int]? = nil}struct Foo { ↓let foo: Set<String>? = nil}class Foo { ↓var foo: [Int]? { return nil }}class Foo { ↓let foo: [Int]? { return nil }()}class Foo { ↓var foo: Set<String>? { return nil }}class Foo { ↓let foo: Set<String>? { return nil }()}struct Foo { ↓var foo: [Int]? { return nil }}struct Foo { ↓let foo: [Int]? { return nil }()}struct Foo { ↓var foo: Set<String>? { return nil }}struct Foo { ↓let foo: Set<String>? { return nil }()}enum Foo { ↓var foo: [Int]? { return nil }}enum Foo { ↓let foo: [Int]? { return nil }()}enum Foo { ↓var foo: Set<String>? { return nil }}enum Foo { ↓let foo: Set<String>? { return nil }()}class Foo { func ↓foo() -> [T]? {}}class Foo { func ↓foo() -> [String: String]? {}}class Foo { func ↓foo() -> [String: [String: String]]? {}}class Foo { func ↓foo() -> [String: [String: String]?] {}}class Foo { func ↓foo() -> Set<Int>? {}}class Foo { static func ↓foo() -> [T]? {}}class Foo { static func ↓foo() -> [String: String]? {}}class Foo { static func ↓foo() -> [String: [String: String]]? {}}class Foo { static func ↓foo() -> [String: [String: String]?] {}}class Foo { static func ↓foo() -> Set<Int>? {}}class Foo { func ↓foo() -> ([Int]?) -> String {}}class Foo { func ↓foo() -> ([Int]) -> [String]? {}}struct Foo { func ↓foo() -> [T]? {}}struct Foo { func ↓foo() -> [String: String]? {}}struct Foo { func ↓foo() -> [String: [String: String]]? {}}struct Foo { func ↓foo() -> [String: [String: String]?] {}}struct Foo { func ↓foo() -> Set<Int>? {}}struct Foo { static func ↓foo() -> [T]? {}}struct Foo { static func ↓foo() -> [String: String]? {}}struct Foo { static func ↓foo() -> [String: [String: String]]? {}}struct Foo { static func ↓foo() -> [String: [String: String]?] {}}struct Foo { static func ↓foo() -> Set<Int>? {}}struct Foo { func ↓foo() -> ([Int]?) -> String {}}struct Foo { func ↓foo() -> ([Int]) -> [String]? {}}enum Foo { func ↓foo() -> [T]? {}}enum Foo { func ↓foo() -> [String: String]? {}}enum Foo { func ↓foo() -> [String: [String: String]]? {}}enum Foo { func ↓foo() -> [String: [String: String]?] {}}enum Foo { func ↓foo() -> Set<Int>? {}}enum Foo { static func ↓foo() -> [T]? {}}enum Foo { static func ↓foo() -> [String: String]? {}}enum Foo { static func ↓foo() -> [String: [String: String]]? {}}enum Foo { static func ↓foo() -> [String: [String: String]?] {}}enum Foo { static func ↓foo() -> Set<Int>? {}}enum Foo { func ↓foo() -> ([Int]?) -> String {}}enum Foo { func ↓foo() -> ([Int]) -> [String]? {}}class Foo { func foo(↓input: [String: String]?) {}}class Foo { func foo(↓input: [String: [String: String]]?) {}}class Foo { func foo(↓input: [String: [String: String]?]) {}}class Foo { func foo(↓↓input: [String: [String: String]?]?) {}}class Foo { func foo<K, V>(_ dict1: [K: V], ↓_ dict2: [K: V]?) -> [K: V]}class Foo { func foo<K, V>(dict1: [K: V], ↓dict2: [K: V]?) -> [K: V]}class Foo { static func foo(↓input: [String: String]?) {}}class Foo { static func foo(↓input: [String: [String: String]]?) {}}class Foo { static func foo(↓input: [String: [String: String]?]) {}}class Foo { static func foo(↓↓input: [String: [String: String]?]?) {}}class Foo { static func foo<K, V>(_ dict1: [K: V], ↓_ dict2: [K: V]?) -> [K: V]}class Foo { static func foo<K, V>(dict1: [K: V], ↓dict2: [K: V]?) -> [K: V]}struct Foo { func foo(↓input: [String: String]?) {}}struct Foo { func foo(↓input: [String: [String: String]]?) {}}struct Foo { func foo(↓input: [String: [String: String]?]) {}}struct Foo { func foo(↓↓input: [String: [String: String]?]?) {}}struct Foo { func foo<K, V>(_ dict1: [K: V], ↓_ dict2: [K: V]?) -> [K: V]}struct Foo { func foo<K, V>(dict1: [K: V], ↓dict2: [K: V]?) -> [K: V]}struct Foo { static func foo(↓input: [String: String]?) {}}struct Foo { static func foo(↓input: [String: [String: String]]?) {}}struct Foo { static func foo(↓input: [String: [String: String]?]) {}}struct Foo { static func foo(↓↓input: [String: [String: String]?]?) {}}struct Foo { static func foo<K, V>(_ dict1: [K: V], ↓_ dict2: [K: V]?) -> [K: V]}struct Foo { static func foo<K, V>(dict1: [K: V], ↓dict2: [K: V]?) -> [K: V]}enum Foo { func foo(↓input: [String: String]?) {}}enum Foo { func foo(↓input: [String: [String: String]]?) {}}enum Foo { func foo(↓input: [String: [String: String]?]) {}}enum Foo { func foo(↓↓input: [String: [String: String]?]?) {}}enum Foo { func foo<K, V>(_ dict1: [K: V], ↓_ dict2: [K: V]?) -> [K: V]}enum Foo { func foo<K, V>(dict1: [K: V], ↓dict2: [K: V]?) -> [K: V]}enum Foo { static func foo(↓input: [String: String]?) {}}enum Foo { static func foo(↓input: [String: [String: String]]?) {}}enum Foo { static func foo(↓input: [String: [String: String]?]) {}}enum Foo { static func foo(↓↓input: [String: [String: String]?]?) {}}enum Foo { static func foo<K, V>(_ dict1: [K: V], ↓_ dict2: [K: V]?) -> [K: V]}enum Foo { static func foo<K, V>(dict1: [K: V], ↓dict2: [K: V]?) -> [K: V]}