15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SwiftLint】全ルールまとめ

Last updated at Posted at 2021-06-12

SwiftLintのデフォルトで有効/無効になっているルールについて調べる機会があったので、ついでにまとめてみました。例については一部しか載せてないので、もっと詳細に知りたい方は各ルールの公式リファレンスを見た方がいいです。
全部で205個ルールあります。

  • Default:87
  • Opt-in:118

※2021年6月時点の最新版(v0.43.1)を対象としています。

Default

デフォルトで有効になっているルール

Block Based KVO

Swift3.2以降の場合、keypathをもつ新しいブロックベースのKVO APIを使うべき。
(observerValue()をoverrideするのではなく、observe()を呼び出すべき)
https://realm.github.io/SwiftLint/block_based_kvo.html

block_based_kvo
// bad
class Foo: NSObject {
  override func observeValue(forKeyPath keyPath: String?, of object: Any?,
                              change: [NSKeyValueChangeKey : Any]?,
                              context: UnsafeMutableRawPointer?) {}
}
 
// good
let observer = foo.observe(\.value, options: [.new]) { (foo, change) in
   print(change.newValue)
}

Class Delegate Protocol

Delegate protocolはweakで保持される可能性があるため、class-onlyにするべき。
https://realm.github.io/SwiftLint/class_delegate_protocol.html

class_delegate_protocol
// bad
protocol FooDelegate {}
 
// good
protocol FooDelegate: class {}

Closing Brace Spacing

}の後に)が続く場合は、それらの間に空白が無いようにすべき。
https://realm.github.io/SwiftLint/closing_brace.html

closing_brace
// bad
[].map({ } )
 
// good
[].map({ })

Closure Parameter Position

クロージャのパラメータは開き括弧({)と同じ行にあるべき。
https://realm.github.io/SwiftLint/closure_parameter_position.html

closure_parameter_position
// bad
[1, 2].map {
    number in
    number + 1
}
 
// good
[1, 2].map { number in
    number + 1
}

Colon Spacing

コロン(:)は、型を指定するときは識別子の後ろ、Dictonaryではkeyの後ろにあるべき。
https://realm.github.io/SwiftLint/colon.html

colon
// bad
let abc:Void
let abc :Void
let abc : Void
let abc: [Void:Void]
let abc: [Void :Void]
let abc: [Void : Void]
 
// good
let abc: Void
let abc: [Void: Void]

Comma Spacing

カンマ(,)の前にスペースがあるべきではない。カンマの後ろにはスペースがあるべき。
https://realm.github.io/SwiftLint/comma.html

comma
// bad
func abc(a: String,b: String) { }
func abc(a: String ,b: String) { }
func abc(a: String , b: String) { }
 
// good
func abc(a: String, b: String) { }

Comment Spacing

コメントする場合、スラッシュ(//)の後ろにスペースを入れるべき。
https://realm.github.io/SwiftLint/comment_spacing.html

comment_spacing
// bad
//hogehoge
 
// good
// hogehoge

Compiler Protocol Init

コンパイラプロトコルで定義されているイニシャライザは直接呼び出すべきではない。
https://realm.github.io/SwiftLint/compiler_protocol_init.html

compiler_protocol_init
// bad
let set = Set(arrayLiteral: 1, 2)
let set = Set.init(arrayLiteral: 1, 2)
 
// good
let set: Set<Int> = [1, 2]
let set = Set(array)

Computed Accessors Order

getterとsetterの順を統一すべき。基本はgetter→setterの順。
https://realm.github.io/SwiftLint/computed_accessors_order.html

computed_accessors_order
// bad
class Foo {
    var foo: Int {
        set {
            print(newValue)
        }
        get {
            return 20
        }
    }
}

// good
class Foo {
    var foo: Int {
        get {
            return 20
        }
        set {
            print(newValue)
        }
    }
}

setter→getterにする場合は以下を参照。

Control Statement

if, for, guard, switch, while, catchは条件式や引数を、必要以上に括弧(())で囲むべきではない。
https://realm.github.io/SwiftLint/control_statement.html

control_statement
// bad
if (condition) {
 
// good
if condition {

Custom Rules

.swiftlint.ymlに記述したcustome_rulesを実行する。
https://realm.github.io/SwiftLint/custom_rules.html

Cyclomatic Complexity

関数内の処理を複雑にするべきではない(もっと簡潔に書くべき)。
https://realm.github.io/SwiftLint/cyclomatic_complexity.html

cyclomatic_complexity
// bad
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
        }
    }
}

// good
func f1() {
    if true {
        for _ in 1..5 { }
    }
    if false { }
}

もう少し詳細に説明すると「関数内の処理は循環的複雑度を10以下にするべき」というルール。

循環的複雑度(英: Cyclomatic complexity)とは、ソフトウェア測定法の一種である。Thomas McCabe が開発したもので、プログラムの複雑度を測るのに使われる。プログラムのソースコードから、線形的に独立した経路の数を直接数える。
wiki

Deployment Target

@availableなどを使う場合は、Deployment Targetを満たす古いバージョンを指定すべきではない。
https://realm.github.io/SwiftLint/deployment_target.html

Deployment Targetが13.0の場合
スクリーンショット 2021-06-09 4.13.37.png

deployment_target
// bad
@available(iOS 6.0, *)
class A {}

if #available(iOS 6.0, *) {}

// good
@available(iOS 14.0, *)
class A {}

if #available(iOS 14.0, *) {}

Discouraged Direct Initialization

有害な可能性のある型を直接初期化すべきではない。
https://realm.github.io/SwiftLint/discouraged_direct_init.html

discouraged_direct_init
// bad
UIDevice()
Bundle()
let foo = UIDevice()
let foo = Bundle()
let foo = Bundle.init()
 
// good
let foo = UIDevice.current
let foo = Bundle.main
let foo = Bundle.init(path: "bar")

Duplicate Enum Cases

enumには同じケース名を含めれない。
https://realm.github.io/SwiftLint/duplicate_enum_cases.html

duplicate_enum_cases
// bad
enum PictureImport {
    case add(image: UIImage)
    case addURL(url: URL)
    case add(data: Data)
}

// good
enum PictureImport {
    case addImage(image: UIImage)
    case addData(data: Data)
}

Duplicate Imports

インポートは一意であるべき。同じインポートをするべきではない。
https://realm.github.io/SwiftLint/duplicate_imports.html

duplicate_imports
// bad
import Foundation
import Dispatch
import Foundation

// good
import Foundation
import Dispatch

Duplicated Key in Dictionary Literal

Dictionaryでは同じKeyを持つべきではない。
https://realm.github.io/SwiftLint/duplicated_key_in_dictionary_literal.html

duplicated_key_in_dictionary_literal
// bad
    [
        foo: "1",
        bar: "2",
        foo: "3",

    ]
// good
    [
        foo: "1",
        bar: "2"
    ]

Dynamic Inline

dynamic@inline(__always)を同時に使うべきではない。
https://realm.github.io/SwiftLint/dynamic_inline.html

dynamic_inline
// bad
class C {
  @inline(__always) dynamic func f() {}
}

// good
class C {
  dynamic func f() {}
}

Empty Enum Arguments

enumの連想値が使われていない場合は、引数を省略すべき。
https://realm.github.io/SwiftLint/empty_enum_arguments.html

empty_enum_arguments
// bad
switch foo {
  case .bar(_): break
}
 
// good
switch foo {
  case .bar: break
}

Empty Parameters

Void ->より() ->を使うべき。
https://realm.github.io/SwiftLint/empty_parameters.html

empty_parameters
// bad
let abc: (Void) -> Void = {}

// good
let abc: () -> Void = {}

Empty Parentheses with Trailing Closure

トレイリングクロージャを使う場合、メソッド呼び出し後に空括弧()を書くべきではない。
https://realm.github.io/SwiftLint/empty_parentheses_with_trailing_closure.html

empty_parentheses_with_trailing_closure
// bad
[1, 2].map() { $0 + 1 }

// good
[1, 2].map { $0 + 1 }

File Length

ファイルにあまりにも多くの行があってはならない。(ファイル内の処理を別ファイルに分割するなどした方が良い)
https://realm.github.io/SwiftLint/file_length.html

file_length
// bad
print("swiftlint")
print("swiftlint")
print("swiftlint")
...

For Where

for文内にif文が1つしかない場合はwhereを使うべき。
https://realm.github.io/SwiftLint/for_where.html

for_where
// bad
for user in users {
  if user.id == 1 { return true }
}

// good
for user in users where user.id == 1 { }

Force Cast

強制キャスト(as!)は使用すべきではない。
https://realm.github.io/SwiftLint/force_cast.html

force_cast
// bad
NSNumber() as! Int

// good
NSNumber() as? Int

Force Try

強制トライ(try!)は使用すべきではない。
https://realm.github.io/SwiftLint/force_try.html

force_try
// bad
func a() throws {}
try! a()
// good
func a() throws {}
do {
  try a()
} catch {}

Function Body Length

関数内はあまりにも多くの行にまたがるべきではない。
https://realm.github.io/SwiftLint/function_body_length.html

Function Parameter Count

関数の引数の数は少なくするべき(引数は5つ以下にするべき)
https://realm.github.io/SwiftLint/function_parameter_count.html

function_parameter_count
// bad
func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}

// good
func f(a: Int, b: Int, c: Int, d: Int, e: Int) {}

Generic Type Name

ジェネリック型名は英数字のみを使用し、大文字で始め、1~20文字にするべき。
https://realm.github.io/SwiftLint/generic_type_name.html

generic_type_name
// bad
func foo<T_Foo>() {}
func foo<TTTTTTTTTTTTTTTTTTTTT>() {}
 
// good
func foo<T>() {}

Identifier Name

識別子名には、英数字のみを使用し、小文字で始まるか、大文字のみを使用する必要がある。 例外として、変数名が静的で不変であると宣言されている場合、変数名は大文字で始まる場合がある。 変数名は長すぎても短すぎてもいけない。
https://realm.github.io/SwiftLint/identifier_name.html

identifier_name
// bad
let MyLet = 0
let _myLet = 0
let myExtremelyVeryVeryVeryVeryVeryVeryLongLet = 0

// good
let myLet = 0
let URL: NSURL? = nil

Implicit Getter

read-onlyのコンピューテッドプロパティとサブスクリプトでは、getを使うべきではない。
https://realm.github.io/SwiftLint/implicit_getter.html

implicit_getter
// bad
class Foo {
    var foo: Int {
        get {
            return 20
        }
    }
}

// good
class Foo {
    var foo: Int {
        get { return 3 }
        set { _abc = newValue }
    }
}

Inclusive Language

識別子は、人種、性別、または社会経済的地位に基づく人々のグループに対する差別を避ける言葉を使用する必要がある。
https://realm.github.io/SwiftLint/inclusive_language.html

inclusive_language
// bad
let slave = "abc"

enum ListType {
    case whitelist
    case blacklist
}

Inert Defer

deferが親スコープの最後にある場合、その場で実行される。
https://realm.github.io/SwiftLint/inert_defer.html

inert_defer
// bad
func example0() {
    defer { /* deferred code */ }
}

// good
func example3() {
    defer { /* deferred code */ }

    print("other code")
}

Is Disjoint

Set.intersection(_:).isEmptyよりSet.isDisjoint(with:)を使うべき。
https://realm.github.io/SwiftLint/is_disjoint.html

is_disjoint
// bad
_ = Set(syntaxKinds).intersection(commentAndStringKindsSet).isEmpty

// good
_ = Set(syntaxKinds).isDisjoint(with: commentAndStringKindsSet)

Large Tuple

タプルのメンバーは多すぎてはいけない。多い場合は代わりにカスタムタイプを作成するべき。
https://realm.github.io/SwiftLint/large_tuple.html

large_tuple
// bad
let foo: (Int, Int, Int)

// good
let foo: (Int, Int)

Leading Whitespace

ファイルの先頭に空白があってはいけない。
https://realm.github.io/SwiftLint/leading_whitespace.html

leading_whitespace
// bad
 // hoge

// good
// hoge

Legacy CGGeometry Functions

構造体のエクステンションのプロパティとメソッドは、従来の関数より優先すべき。
https://realm.github.io/SwiftLint/legacy_cggeometry_functions.html

legacy_cggeometry_functions
// bad
CGRectGetWidth(rect)
CGRectGetHeight(rect)
CGRectGetMinX(rect)
CGRectGetMidX(rect)
CGRectGetMaxX(rect)
CGRectGetMinY(rect)
CGRectGetMidY(rect)
CGRectGetMaxY(rect)
CGRectIsNull(rect)
CGRectIsEmpty(rect)
CGRectIsInfinite(rect)
CGRectStandardize(rect)
CGRectIntegral(rect)
CGRectInset(rect, 10, 5)
CGRectOffset(rect, -2, 8.3)
CGRectUnion(rect1, rect2)
CGRectIntersection(rect1, rect2)
CGRectContainsRect(rect1, rect2)
CGRectContainsPoint(rect, point)
CGRectIntersectsRect(rect1, rect2)
 
// good
rect.width
rect.height
rect.minX
rect.midX
rect.maxX
rect.minY
rect.midY
rect.maxY
rect.isNull
rect.isEmpty
rect.isInfinite
rect.standardized
rect.integral
rect.insetBy(dx: 5.0, dy: -7.0)
rect.offsetBy(dx: 5.0, dy: -7.0)
rect1.union(rect2)
rect1.intersect(rect2)
rect1.contains(rect2)
rect.contains(point)
rect1.intersects(rect2)

Legacy Constant

構造スコープ定数は従来のグローバル定数よりも優先すべき。
https://realm.github.io/SwiftLint/legacy_constant.html

legacy_constant
// bad
CGRectInfinite
CGPointZero
CGRectZero
CGSizeZero
NSZeroPoint
NSZeroRect
NSZeroSize
CGRectNull
CGFloat(M_PI)
Float(M_PI)
 
// good
CGRect.infinite
CGPoint.zero
CGRect.zero
CGSize.zero
NSPoint.zero
NSRect.zero
NSSize.zero
CGRect.null
CGFloat.pi
Float.pi

Legacy Constructor

Swiftのコンストラクタは従来のコンビニエンス関数よりも優先すべき。
https://realm.github.io/SwiftLint/legacy_constructor.html

legacy_constructor
// bad
CGPointMake(10, 10)
CGPointMake(xVal, yVal)
CGPointMake(calculateX(), 10)
CGSizeMake(10, 10)
CGSizeMake(aWidth, aHeight)
CGRectMake(0, 0, 10, 10)
CGRectMake(xVal, yVal, width, height)
CGVectorMake(10, 10)
CGVectorMake(deltaX, deltaY)
NSMakePoint(10, 10)
NSMakePoint(xVal, yVal)
NSMakeSize(10, 10)
NSMakeSize(aWidth, aHeight)
NSMakeRect(0, 0, 10, 10)
NSMakeRect(xVal, yVal, width, height)
NSMakeRange(10, 1)
NSMakeRange(loc, len)
UIEdgeInsetsMake(0, 0, 10, 10)
UIEdgeInsetsMake(top, left, bottom, right)
NSEdgeInsetsMake(0, 0, 10, 10)
NSEdgeInsetsMake(top, left, bottom, right)
CGVectorMake(10, 10)
NSMakeRange(10, 1)
UIOffsetMake(0, 10)
UIOffsetMake(horizontal, vertical)
 
// good
CGPoint(x: 10, y: 10)
CGPoint(x: xValue, y: yValue)
CGSize(width: 10, height: 10)
CGSize(width: aWidth, height: aHeight)
CGRect(x: 0, y: 0, width: 10, height: 10)
CGRect(x: xVal, y: yVal, width: aWidth, height: aHeight)
CGVector(dx: 10, dy: 10)
CGVector(dx: deltaX, dy: deltaY)
NSPoint(x: 10, y: 10)
NSPoint(x: xValue, y: yValue)
NSSize(width: 10, height: 10)
NSSize(width: aWidth, height: aHeight)
NSRect(x: 0, y: 0, width: 10, height: 10)
NSRect(x: xVal, y: yVal, width: aWidth, height: aHeight)
NSRange(location: 10, length: 1)
NSRange(location: loc, length: len)
UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 10)
UIEdgeInsets(top: aTop, left: aLeft, bottom: aBottom, right: aRight)
NSEdgeInsets(top: 0, left: 0, bottom: 10, right: 10)
NSEdgeInsets(top: aTop, left: aLeft, bottom: aBottom, right: aRight)
UIOffset(horizontal: 0, vertical: 10)
UIOffset(horizontal: horizontal, vertical: vertical)

Legacy Hashing

hasValueをoverrideするのではなく、hash(into:)関数を使うべき。
https://realm.github.io/SwiftLint/legacy_hashing.html

legacy_hashing
// bad
struct Foo: Hashable {
    let bar: Int = 10

    public var hashValue: Int {
        return bar
    }
}
 
// good
struct Foo: Hashable {
  let bar: Int = 10

  func hash(into hasher: inout Hasher) {
    hasher.combine(bar)
  }
}

Legacy NSGeometry Functions

構造体のエクステンションのプロパティとメソッドは、従来の関数より優先すべき。
https://realm.github.io/SwiftLint/legacy_nsgeometry_functions.html

legacy_nsgeometry_functions
// bad
NSWidth(rect)
NSHeight(rect)
NSMinX(rect)
NSMidX(rect)
NSMaxX(rect)
NSMinY(rect)
NSMidY(rect)
NSMaxY(rect)
NSEqualRects(rect1, rect2)
NSEqualSizes(size1, size2)
NSEqualPoints(point1, point2)
NSEdgeInsetsEqual(insets2, insets2)
NSIsEmptyRect(rect)
NSIntegralRect(rect)
NSInsetRect(rect, 10, 5)
NSOffsetRect(rect, -2, 8.3)
NSUnionRect(rect1, rect2)
NSIntersectionRect(rect1, rect2)
NSContainsRect(rect1, rect2)
NSPointInRect(rect, point)
NSIntersectsRect(rect1, rect2)
 
// good
rect.width
rect.height
rect.minX
rect.midX
rect.maxX
rect.minY
rect.midY
rect.maxY
rect.isEmpty
rect.integral
rect.insetBy(dx: 5.0, dy: -7.0)
rect.offsetBy(dx: 5.0, dy: -7.0)
rect1.union(rect2)
rect1.intersect(rect2)
rect1.contains(rect2)
rect.contains(point)
rect1.intersects(rect2)

Line Length

1行にあまりにも多くの文字を含めるべきではない。(120文字以下にすべき)
https://realm.github.io/SwiftLint/line_length.html

Mark

MARKコメントは有効な形式にするべき。
https://realm.github.io/SwiftLint/mark.html

mark
// bad
//MARK: bad
// MARK:bad
//MARK:bad
//  MARK: bad
// MARK:  bad
// MARK: -bad
// MARK:- bad
// MARK:-bad
//MARK: - bad
//MARK:- bad
//MARK: -bad
//MARK:-bad
// MARK bad
//MARK bad
// MARK - bad
//MARK : bad
// MARKL:
// MARKR 
// MARKK -
/// MARK:
/// MARK bad
//MARK:- Top-Level bad mark
//MARK:- Another bad mark
struct MarkTest {}
// MARK:- Bad mark
extension MarkTest {}

// good
// MARK: good

// MARK: - good

// MARK: -

// BOOKMARK
// BOOKMARKS

Multiple Closures with Trailing Closure

複数のクロージャを引数とする場合、トレイリングクロージャを使うべきではない。
https://realm.github.io/SwiftLint/multiple_closures_with_trailing_closure.html

multiple_closures_with_trailing_closure
// bad
foo.something(param1: { $0 }) { $0 + 1 } 

// good
foo.map { $0 + 1 }

Nesting

型は最大1レベルの深さにネストするべきであり、関数は最大5レベルの深さにネストするべき。
https://realm.github.io/SwiftLint/nesting.html

nesting
// bad
    class Example_0 {
        class Example_1 {
            class Example_2 {}
        }
    }

// good
    class Example_0 {
        class Example_1 {}
    }

No Fallthrough Only

fallthroughは、caseに少なくとも1つのステートメントが含まれている場合にのみ使うべき。
https://realm.github.io/SwiftLint/no_fallthrough_only.html

no_fallthrough_only
// bad
switch myvar {
case 1:
    fallthrough
case 2:
    var a = 1
}

// good
switch myvar {
case 1:
    var a = 1
    fallthrough
case 2:
    var a = 2
}

No Space in Method Call

メソッド名と括弧()の間にスペースを入れてはいけない。
https://realm.github.io/SwiftLint/no_space_in_method_call.html

no_space_in_method_call
// bad
foo ()
// good
foo()

Notification Center Detachment

NotificationCenterに登録した自分自身のobserverはクラスのdeinit内で除去するべき.
https://realm.github.io/SwiftLint/notification_center_detachment.html

notification_center_detachment
// bad
class Foo {
   func bar() {
       NotificationCenter.default.removeObserver(self)
   }
}

// good
class Foo {
   deinit {
       NotificationCenter.default.removeObserver(self)
   }
}

class Foo {
   func bar() {
       NotificationCenter.default.removeObserver(otherObject)
   }
}

NSObject Prefer isEqual

NSObjectのサブクラスは、==の代わりにisEqualを実装するべき。
https://realm.github.io/SwiftLint/nsobject_prefer_isequal.html

nsobject_prefer_isequal
// bad
class AClass: NSObject {
    static func ==(lhs: AClass, rhs: AClass) -> Bool {
        return false
    }
}

// good
class AClass: NSObject {
    override func isEqual(_ object: Any?) -> Bool {
        return true
    }
}

Opening Brace Spacing

{は宣言と同じ行に置き、スペースを1つ入れるべき。
https://realm.github.io/SwiftLint/opening_brace.html

opening_brace
// bad
func abc(){
}

func abc()
{
}

// good
func abc() {
}

Operator Function Whitespace

演算子を定義する時、1つのスペースで囲むべき。
https://realm.github.io/SwiftLint/operator_whitespace.html

operator_whitespace
// bad
func <|(lhs: Int, rhs: Int) -> Int {}

// good
func <| (lhs: Int, rhs: Int) -> Int {}

Orphaned Doc Comment

ドキュメントコメントは宣言の上部に書くべき。
https://realm.github.io/SwiftLint/orphaned_doc_comment.html

orphaned_doc_comment
// bad
/// My great property
// Not a doc string
var myGreatProperty: String!

// good
/// My great property
var myGreatProperty: String!

Private over fileprivate

fileprivateよりprivateを使用するべき。
https://realm.github.io/SwiftLint/private_over_fileprivate.html

private_over_fileprivate
// 例を見てもよくわからない。とりあえずfileprivateはあまり使わない方がいいということは確か

// bad
fileprivate class MyClass {
  fileprivate(set) var myInt = 4
}

fileprivate enum MyEnum {}

// good
class MyClass {
  fileprivate(set) var myInt = 4
}

Private Unit Test

privateのUnit Testは暗黙的にスキップされる(privateにすべきではない)
https://realm.github.io/SwiftLint/private_unit_test.html

private_unit_test
// bad
private class FooTest: XCTestCase {
    func test1() {}
    internal func test2() {}
    public func test3() {}
}

// good
class FooTest: XCTestCase {
    func test1() {}
    internal func test2() {}
    public func test3() {}
}

Protocol Property Accessors Order

プロトコルでプロパティを宣言する場合、アクセサの順番をget``setの順にするべき。
https://realm.github.io/SwiftLint/protocol_property_accessors_order.html

protocol_property_accessors_order
// bad
protocol Foo {
   var bar: String { set get }
}

// good
protocol Foo {
   var bar: String { get set }
}
protocol Foo {
   var bar: String { get }
}
protocol Foo {
   var bar: String { set }
}

Reduce Boolean

reduce(true)reduce(false)よりも.allSatisfy().contains()を使うべき。
https://realm.github.io/SwiftLint/reduce_boolean.html

reduce_boolean
// bad
let allNines = nums.reduce(true) { $0.0 && $0.1 == 9 }
let anyNines = nums.reduce(false) { $0.0 || $0.1 == 9 }

// good
let allNines = nums.allSatisfy { $0 == 9 }
let anyNines = nums.contains { $0 == 9 }

Redundant Discardable Let

関数の戻り値を使わず実行する場合、let _ = foo()より_ = foo()を使うべき。
https://realm.github.io/SwiftLint/redundant_discardable_let.html

redundant_discardable_let
// bad
let _ = foo()

// good
_ = foo()

Redundant @objc Attribute

冗長な@objc宣言は避けるべき。
https://realm.github.io/SwiftLint/redundant_objc_attribute.html

redundant_objc_attribute
// bad
@objc @IBAction private func foo(_ sender: Any) {}
 
// good
@IBAction private func foo(_ sender: Any) {}

Redundant Optional Initialization

Optional型の変数をnilで初期化するのは冗長。
https://realm.github.io/SwiftLint/redundant_optional_initialization.html

redundant_optional_initialization
// bad
var myVar: Int? = nil

// good
var myVar: Int?

Redundant Set Access Control Rule

プロパティのセッターのアクセスレベルが、変数のアクセスレベルと同じ場合、明示的に指定すべきではない。
https://realm.github.io/SwiftLint/redundant_set_access_control.html

redundant_set_access_control
// bad
private(set) private var foo: Int

// good
private(set) public var foo: Int

Redundant String Enum Value

文字列の列挙値は、caseと同じ場合省略できる。
https://realm.github.io/SwiftLint/redundant_string_enum_value.html

redundant_string_enum_value
// bad
enum Numbers: String {
  case one = "one"
  case two = "two"
}

// good
enum Numbers: String {
  case one
  case two
}

Redundant Void Return

関数宣言でVoidを返すのは冗長である。
https://realm.github.io/SwiftLint/redundant_void_return.html

redundant_void_return
// bad
func foo() -> Void {}
 
// good
func foo() {}

Returning Whitespace

戻り値の矢印と型は1つのスペースを開けるか、別の行で区切るべき。
https://realm.github.io/SwiftLint/return_arrow_whitespace.html

return_arrow_whitespace
// bad
func abc()->Int {}
func abc() ->[Int] {}
func abc()-> (Int, Int) {}

// good
func abc() -> Int {}
func abc() -> 
          Int {}
func abc()
      -> Int {}

Shorthand Operator

省略系の演算子を使うべき。
https://realm.github.io/SwiftLint/shorthand_operator.html

shorthand_operator
// bad
foo = foo - 1
foo = foo - aVariable

// good
foo -= 1
foo -= variable

Statement Position

elsecatchは前の宣言に1つのスペースを入れ、同じ行に配置されるべき。
https://realm.github.io/SwiftLint/statement_position.html

statement_position
// bad
}else if {

}  else {

}
catch {

}
      catch {

 
// good
} else if {

} else {

} catch {

Superfluous Disable Command

無効化されたルールが無効化された領域で違反を起こさなかった場合、SwiftLintのdisableコマンドは不要。
https://realm.github.io/SwiftLint/superfluous_disable_command.html

Switch and Case Statement Alignment

case文はそれを囲むswitch文と同じインデントにすべき。
https://realm.github.io/SwiftLint/switch_case_alignment.html

switch_case_alignment
// bad
switch someBool {
    case true:
        print("red")
    case false:
        print("blue")
}

// good
switch someBool {
case true:
    print("red")
case false:
    print("blue")
}

Syntactic Sugar

シンタックスシュガー(糖衣構文)を使うべき。Arrayの代わりに[Int]を使うなど。
https://realm.github.io/SwiftLint/syntactic_sugar.html

syntactic_sugar
// bad
let x: Array<String>
 
// good
let x: [Int]

Todo

TODOFIXMEは解決すべき。
https://realm.github.io/SwiftLint/todo.html

todo
// bad

// TODO:
// FIXME:

Trailing Comma

配列とDictionaryの末尾のカンマは付けるべきではない。
https://realm.github.io/SwiftLint/trailing_comma.html

trailing_comma
// bad
let foo = [1, 2, 3,] 

// good
let foo = [1, 2, 3]

Trailing Newline

ファイルは末尾に1つの改行を持つべき。
https://realm.github.io/SwiftLint/trailing_newline.html

Trailing Semicolon

行の末尾にセミコロン;を付けるべきではない。
https://realm.github.io/SwiftLint/trailing_semicolon.html

trailing_semicolon
// bad
let a = 0;

// good
let a = 0

Trailing Whitespace

行の末尾にスペースがあってはいけない。
https://realm.github.io/SwiftLint/trailing_whitespace.html

Type Body Length

型内はあまりにも多くの行にまたがってはいけない。
https://realm.github.io/SwiftLint/type_body_length.html

Type Name

型名は英数字のみを含み、大文字で始まり、3~40文字の長さにする必要がある。
https://realm.github.io/SwiftLint/type_name.html

type_name
// bad
class myType {}

// good
class MyType {}

Unneeded Break in Switch

不要なbreakの使用は避けるべき。
https://realm.github.io/SwiftLint/unneeded_break_in_switch.html

unneeded_break_in_switch
// bad
switch foo {
case .bar:
    something()
    break
}

// good
switch foo {
case .bar:
    break
}

Unused Capture List

キャプチャリスト内の未使用の参照は削除すべき。
https://realm.github.io/SwiftLint/unused_capture_list.html

unused_capture_list
// bad
[1, 2].map { [weak self] num in
    print(num)
}

// good
[1, 2].map { num in
    print(num)
}

[1, 2].map { [weak self] num in
    self?.handle(num)
}

Unused Closure Parameter

クロージャで使用されてないパラメータは_に置き換えるべき。
https://realm.github.io/SwiftLint/unused_closure_parameter.html

unused_closure_parameter
// bad
[1, 2].map { number in
 return 3
}

// good
[1, 2].map { number in
 number + 1 
}

Unused Control Flow Label

未使用の制御フローラベルは削除すべき。
https://realm.github.io/SwiftLint/unused_control_flow_label.html

unused_control_flow_label
// bad
loop: while true { break }
 
// good
loop: while true { break loop }

Unused Enumerated

インデックスかアイテムが使用されてない場合は、.enumerated()を削除すべき。
https://realm.github.io/SwiftLint/unused_enumerated.html

unused_enumerated
// bad
for (_, foo) in bar.enumerated() { }

// good
for (index, foo) in bar.enumerated() { }

Unused Optional Binding

let _ =より!= nilを使用すべき。
https://realm.github.io/SwiftLint/unused_optional_binding.html

unused_optional_binding
// bad
if let _ = a { }

// good
if a != nil { }

Unused Setter Value

セッターの値は使われるべき。
https://realm.github.io/SwiftLint/unused_setter_value.html

unused_setter_value
var aValue: String {
    get {
        return Persister.shared.aValue
    }
    set {
        // bad
        Persister.shared.aValue = aValue
        // good
        Persister.shared.aValue = newValue
    }
}

Valid IBInspectable

@IBInspectableはサポートされている型の変数のみに適用されるべきであり、その型を明示的にする必要がある。
https://realm.github.io/SwiftLint/valid_ibinspectable.html

valid_ibinspectable
// bad
class Foo {
  @IBInspectable private let x: Int
}
 
// good
class Foo {
  @IBInspectable private var x: Int
}

Vertical Parameter Alignment

関数の定義時、パラメータが複数行にまたがっている場合は垂直方向に揃えるべき。
https://realm.github.io/SwiftLint/vertical_parameter_alignment.html

vertical_parameter_alignment
// bad
func validateFunction(_ file: SwiftLintFile, kind: SwiftDeclarationKind,
         dictionary: SourceKittenDictionary) { }

// good
func validateFunction(_ file: SwiftLintFile, kind: SwiftDeclarationKind,
                      dictionary: SourceKittenDictionary) { }

Vertical Whitespace

空白行は1行に抑えるべき。
https://realm.github.io/SwiftLint/vertical_whitespace.html

Void Return

-> ()より-> Voidを使うべき。
https://realm.github.io/SwiftLint/void_return.html

void_return
// bad
let abc: () -> () = { }

// good
let abc: () -> Void = { }

Weak Delegate

Delegateは循環参照を避けるために弱参照とすべき。
https://realm.github.io/SwiftLint/weak_delegate.html

weak_delegate
// bad
var delegate: SomeProtocol?

// good
weak var delegate: SomeProtocol?

XCTFail Message

XCTFailの呼び出しには、アサーションの説明を含めるべき。
https://realm.github.io/SwiftLint/xctfail_message.html

xctfail_message
// bad
func testFoo() {
  XCTFail()
}

// good
func testFoo() {
  XCTFail("bar")
}

Opt-in

デフォルトで無効になっているルール

AnyObject Protocol

class-onlyなプロトコルにはclassよりAnyObjectを使うべき。
https://realm.github.io/SwiftLint/anyobject_protocol.html

anyobject_protocol
// bad
protocol SomeClassOnlyProtocol: class {}

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {}

// good
protocol SomeProtocol {}

protocol SomeClassOnlyProtocol: AnyObject {}

Array Init

シーケンスを配列に変換する場合、seq.map { $0 }よりArray(seq)を使うべき。
https://realm.github.io/SwiftLint/array_init.html

array_init
// bad
foo.map { $0 }

// good
Array(foo)

Attributes

属性は、関数と型では別の行にあるべきだが、変数とimportの場合は同じ行にあるべき。
https://realm.github.io/SwiftLint/attributes.html

attributes
// bad
@available(iOS 9.0, *) func animate(view: UIStackView)

@available(iOS 9.0, *) class UIStackView

@objc
var x: String

@testable
import SourceKittenFramework


// good
@available(iOS 9.0, *)
func animate(view: UIStackView)

@available(iOS 9.0, *)
class UIStackView

@objc var x: String

@testable import SourceKittenFramework

Balanced XCTest life-cycle

テストクラスはsetUp()tearDown()をバランスよく実装すべき。
https://realm.github.io/SwiftLint/balanced_xctest_lifecycle.html

balanced_xctest_lifecycle
// bad
final class FooTests: XCTestCase {
    override func setUp() {}
}

final class FooTests: XCTestCase {
    override func setUpWithError() throws {}
}

// good
final class FooTests: XCTestCase {
    override func setUp() {}
    override func tearDown() {}
}

Capture Variable

作成時にクロージャーが変数をキャプチャーする混乱を避けるために、非定数変数はクロージャーのキャプチャーリストにリストすべきではない。
https://realm.github.io/SwiftLint/capture_variable.html

capture_variable
// bad
var j: Int = 0

let closure: () -> Void = { [j] in
    print(j)
}

closure()
j = 1
closure()
 
// good
var j: Int!
j = 0

let closure: () -> Void = { [j] in
    print(j)
}

closure()
j = 1
closure()

Closure Body Length

クロージャ内はあまりにも多くの行にまたがってはいけない。
https://realm.github.io/SwiftLint/closure_body_length.html

closure_body_length
// bad
foo.bar { toto in
    let a0 = 0
    let a0 = 0
    let a0 = 0
    ...
}
 
// good
foo.bar { toto in
    let a0 = 0
}

Closure End Indentation

クロージャの終了は、開始した行と同じインデントにするべき。
https://realm.github.io/SwiftLint/closure_end_indentation.html

closure_end_indentation
// bad
SignalProducer(values: [1, 2, 3])
   .startWithNext { number in
       print(number)
}

// good
SignalProducer(values: [1, 2, 3])
   .startWithNext { number in
       print(number)
   }

Closure Spacing

クロージャ内は各括弧の内側に1つのスペースがあるべき。
https://realm.github.io/SwiftLint/closure_spacing.html

closure_spacing
// bad
[].filter {$0.contains(location)}
 
// good
[].filter { $0.contains(location) }

Collection Element Alignment

コレクション内の全要素は垂直に揃うべき。
https://realm.github.io/SwiftLint/collection_alignment.html

collection_alignment
// bad
let abc = [
    "alpha": "a",
     "beta": "b",
    "gamma": "g",
    "delta": "d",
  "epsilon": "e"
]
 
// good
let abc = [
    "alpha": "a",
    "beta": "b",
    "gamma": "g",
    "delta": "d",
    "epsilon": "e"
]

Conditional Returns on Newline

guardifreturnする際は次の行で行うべき。
https://realm.github.io/SwiftLint/conditional_returns_on_newline.html

conditional_returns_on_newline
// bad
guard true else { return }
 
// good
guard true else {
  return
}

Contains Over Filter Count

filter(where:).countを0と比較するよりcontainsを使うべき。
https://realm.github.io/SwiftLint/contains_over_filter_count.html

contains_over_filter_count
// bad
let result = myList.filter(where: { $0 % 2 == 0 }).count > 0
let result = myList.filter(where: { $0 % 2 == 0 }).count == 0
 
// good
let result = myList.contains { $0 % 2 == 0 }
let result = myList.filter { $0 % 2 == 0 }.count > 1

Contains Over Filter Is Empty

filter(where:).isEmptyを使うよりcontainsを使うべき。
https://realm.github.io/SwiftLint/contains_over_filter_is_empty.html

contains_over_filter_is_empty
// bad
let result = myList.filter(where: { $0 % 2 == 0 }).isEmpty
let result = myList.filter { $0 % 2 == 0 }.isEmpty

// good
let result = myList.contains(where: { $0 % 2 == 0 })
let result = myList.filter(where: { $0 % 2 == 0 }).count > 1

Contains over first not nil

first(where:) != nilfirstIndex(where:) != nilよりもcontainsを使うべき。
https://realm.github.io/SwiftLint/contains_over_first_not_nil.html

contains_over_first_not_nil
// bad
myList.first { $0 % 2 == 0 } != nil
myList.firstIndex { $0 % 2 == 0 } != nil

// good
myList.contains { $0 % 2 == 0 }
myList.contains(where: { $0 % 2 == 0 })

Contains over range(of:) comparison to nil

range(of:) != nilrange(of:) == nilよりもcontainsを使うべき。
https://realm.github.io/SwiftLint/contains_over_range_nil_comparison.html

contains_over_range_nil_comparison
// bad
myString.range(of: "Test") != nil
myString.range(of: "Test") == nil
 
// good
myString.contains("Test")
!myString.contains("Test")

Convenience Type

staticメンバーのみをホストするために使われる型は、インスタンス化を避けるために、caseのない列挙型として実装すべき。
https://realm.github.io/SwiftLint/convenience_type.html

convenience_type
// bad
struct Math {
    public static let pi = 3.14
}
class Math {
    public static let pi = 3.14
}

// good
enum Math {
    public static let pi = 3.14
}

// 継承を伴う場合はOK
class MathViewController: UIViewController {
    public static let pi = 3.14
}

// Obj-Cに見えるクラスはOK
@objc class Math: NSObject {
    public static let pi = 3.14
}

// 静的でない型もある場合はOK
struct Math {
    public static let pi = 3.14
    public let randomNumber = 2
}

Discarded Notification Center Observer

ブロックを使用して通知を登録する場合、返されるオブザーバを保持し、後で削除可能な状態にするべきである。
(オブザーバを定数に入れたり、同じオブザーバを受け取れるようにメソッド化するなど、再度取得可能な状態にするべき)
https://realm.github.io/SwiftLint/discarded_notification_center_observer.html

discarded_notification_center_observer
// bad
nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil) { }
 
// good
let foo = nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil) { }

func foo() -> Any {
   return nc.addObserver(forName: .NSSystemTimeZoneDidChange, object: nil, queue: nil, using: { })
}

Discouraged Assert

assert(false)を使うより、assertionFailure()またはpreconditionFailure()を使用するべき。
https://realm.github.io/SwiftLint/discouraged_assert.html

discouraged_assert
// bad
assert(false)
assert(false, "foobar")
 
// good
preconditionFailure("foobar")
assertionFailure("foobar")
assert(true)

Discouraged None Name

Optional<T>.noneと競合の可能性のあるcase名やstaticメンバー名は推奨しない。
https://realm.github.io/SwiftLint/discouraged_none_name.html

discouraged_none_name
// bad
enum MyEnum {
    case none
}

class MyClass {
    static let none = MyClass()
}
 
// good
// 以下はルール的にはセーフだが、noneに似ているので避けた方がいいと思う
enum MyEnum {
    case nOne
}

class MyClass {
    class var nonenone: MyClass { MyClass() }
}

Discouraged Object Literal

オブジェクトリテラルよりイニシャライザを使うべき。
https://realm.github.io/SwiftLint/discouraged_object_literal.html

discouraged_object_literal
// bad
let image = #imageLiteral(resourceName: "image.jpg")
let color = #colorLiteral(red: value, green: value, blue: value, alpha: 1)

// good
let image = UIImage(named: "image")
let color = UIColor(red: value, green: value, blue: value, alpha: 1)

Discouraged Optional Boolean

オプショナルのBool型は使うべきではない。
https://realm.github.io/SwiftLint/discouraged_optional_boolean.html

discouraged_optional_boolean
// bad
var foo: Bool?
let foo: Bool? = nil
 
// good
var foo: Bool
let foo: Bool = true

Discouraged Optional Collection

オプショナルのコレクションを使うより空のコレクションを使うべき。
https://realm.github.io/SwiftLint/discouraged_optional_collection.html

discouraged_optional_collection
// bad
var foo: [Int]?
let foo: [Int]? = nil

// good
var foo: [Int]
let foo: [Int] = []

Empty Collection Literal

コレクションを空の配列やDictionaryと比較するより、isEmptyを使うべき。
https://realm.github.io/SwiftLint/empty_collection_literal.html

empty_collection_literal
// bad
myArray == []
myArray != []
myDict == [:]
myDict != [:]

// good
myArray.isEmpty

Empty Count

countを0と比較するよりもisEmptyを使うべき。
https://realm.github.io/SwiftLint/empty_count.html

empty_count
// bad
[Int]().count == 0
[Int]().count > 0
[Int]().count != 0

// good
[Int]().isEmpty

Empty String

空の文字列と比較するより isEmptyを使うべき。
https://realm.github.io/SwiftLint/empty_string.html

empty_string
// bad
myString == ""
myString != ""
 
// good
myString.isEmpty
!myString.isEmpty

Empty XCTest Method

空のXCTestメソッドは実装すべきではない。
https://realm.github.io/SwiftLint/empty_xctest_method.html

empty_xctest_method
// bad
class TotoTests: XCTestCase {

    override func setUp() {
    }

    override func tearDown() {
    }

    func testFoo() {
    }

}

// good
class TotoTests: XCTestCase {

    var foobar: Foobar?

    override func setUp() {
        super.setUp()
        foobar = Foobar()
    }

    override func tearDown() {
        foobar = nil
        super.tearDown()
    }

    func testFoo() {
        XCTAssertTrue(foobar?.foo)
    }

    func helperFunction() {
    }
}

Enum Case Associated Values Count

列挙型のcaseの連想値は少なくするべき(4つ以下にするべき)
https://realm.github.io/SwiftLint/enum_case_associated_values_count.html

enum_case_associated_values_count
// bad
enum Employee {
    case fullTime(name: String, retirement: Date, age: Int, designation: String, contactNumber: Int)
    case partTime(name: String, contractEndDate: Date, age: Int, designation: String, contactNumber: Int)
}

enum Barcode {
    case upc(Int, Int, Int, Int, Int, Int)
}

// good
enum Employee {
    case fullTime(name: String, retirement: Date, designation: String, contactNumber: Int)
    case partTime(name: String, age: Int, contractEndDate: Date)
}

enum Barcode {
    case upc(Int, Int, Int, Int)
}

ExpiringTodo

TODOとFIXMEは有効期限前に解決すべき。
https://realm.github.io/SwiftLint/expiring_todo.html

expiring_todo
// bad
// TODO: [1/1/2019]
// FIXME: [1/1/2019]
 
// good
// TODO: [12/31/9999]
// FIXME: [12/31/9999]

Explicit ACL

全ての宣言で、アクセス制御レベルのキーワードを明示的に指定すべき。
https://realm.github.io/SwiftLint/explicit_acl.html

explicit_acl
// bad
enum A {}

final class B {}

internal struct C { let d = 5 }

public struct C { let d = 5 }

func a() {}
 
// good
internal enum A {}

public final class B {}

private struct C {}

internal enum A {
 internal enum B {}
}
internal final class Foo {}

Explicit Enum Raw Value

列挙型のcaseにはローバリューを明示的に割り当てるべき。
https://realm.github.io/SwiftLint/explicit_enum_raw_value.html

explicit_enum_raw_value
// bad
enum Numbers: Int {
  case one
  case two
}

// good
enum Numbers: Int {
  case one = 1
  case two = 2
}

Explicit Init

.init()を明示的に呼び出すのは避けるべき。
https://realm.github.io/SwiftLint/explicit_init.html

explicit_init
// bad
[1].flatMap{String.init($0)}
[String.self].map { Type in Type.init(1) }
func foo() -> [String] {
  return [1].flatMap { String.init($0) }
}

// good
[1].flatMap(String.init)
[String.self].map { $0.init(1) }
[String.self].map { type in type.init(1) }

Explicit Self

インスタンス変数と関数はself.で明示的にアクセスするべき。
https://realm.github.io/SwiftLint/explicit_self.html

explicit_self
// bad
struct A {
    func f1() {}
    func f2() {
        f1()
    }
}

struct A {
    let p1: Int
    func f1() {
        _ = p1
    }
}

// good
struct A {
    func f1() {}
    func f2() {
        self.f1()
    }
}

struct A {
    let p1: Int
    func f1() {
        _ = self.p1
    }
}

Explicit Top Level ACL

最上位の定義は、アクセス制御レベルのキーワードを明示的に指定するべき。
https://realm.github.io/SwiftLint/explicit_top_level_acl.html

explicit_top_level_acl
// bad
enum A {
  enum B {}
}

// good
internal enum A {
  enum B {}
}

Explicit Type Interface

プロパティには型を明示的に指定すべき。
https://realm.github.io/SwiftLint/explicit_type_interface.html

explicit_type_interface
// bad
class Foo {
  var myVar = 0
}

// good
class Foo {
  var myVar: Int? = 0
}

Extension Access Modifier

extensionにはアクセス修飾子を使うべき。
https://realm.github.io/SwiftLint/extension_access_modifier.html

extension_access_modifier
// bad
extension Foo {
  var bar: Int { return 1 }
  var baz: Int { return 1 }
}
 
// good
public extension Foo {
  var bar: Int { return 1 }
  var baz: Int { return 1 }
}

extension Foo {
  private var bar: Int { return 1 }
  public var baz: Int { return 1 }
}

Fallthrough

fallthroughは使うべきではない。
https://realm.github.io/SwiftLint/fallthrough.html

fallthrough
// bad
switch foo {
case .bar:
  fallthrough
case .bar2:
  something()
}

// good
switch foo {
case .bar:
  hoge()
case .bar2:
  something()
}

Fatal Error Message

fatalErrorはメッセージを付けるべき。
https://realm.github.io/SwiftLint/fatal_error_message.html

fatal_error_message
// bad
func foo() {
  fatalError("")
}
 
// good
func foo() {
  fatalError("Foo")
}

File Header

各ファイルのヘッダーコメントは、一貫性のあるパターンであるべき。
(ヘッダーコメントの内容は統一すべき的なこと)
https://realm.github.io/SwiftLint/file_header.html

File Name

ファイル名は、ファイル内で宣言されている型やextensionと一致すべき。
https://realm.github.io/SwiftLint/file_name.html

File Name No Space

ファイル名にはスペースが入ってはいけない。
https://realm.github.io/SwiftLint/file_name_no_space.html

File Types Order

ファイル内の型の表示順を指定すべき。
https://realm.github.io/SwiftLint/file_types_order.html

file_types_order
// bad
// `protocol` (サポートする型)は `class` (主となる型)の前に書くべき
class TestViewController: UIViewController {}
protocol TestViewControllerDelegate {
    func didPressTrackedButton()
}

// `extension` は `class` の後に書くべき
extension TestViewController: UITableViewDataSource { // (省略) }
class TestViewController: UIViewController {}

// good
// Supporting Types
protocol TestViewControllerDelegate: AnyObject {
    func didPressTrackedButton()
}

// Main Type
class TestViewController: UIViewController {
    // Type Aliases
    typealias CompletionHandler = ((TestEnum) -> Void)

    // Subtypes
    class TestClass {
        // 10 lines
    }

    struct TestStruct {
        // 3 lines
    }

    enum TestEnum {
        // 5 lines
    }

    // Stored Type Properties
    static let cellIdentifier: String = "AmazingCell"

    // Stored Instance Properties
    var shouldLayoutView1: Bool!
    weak var delegate: TestViewControllerDelegate?
    private var hasLayoutedView1: Bool = false
    private var hasLayoutedView2: Bool = false

    // Computed Instance Properties
    private var hasAnyLayoutedView: Bool {
         return hasLayoutedView1 || hasLayoutedView2
    }

    // IBOutlets
    @IBOutlet private var view1: UIView!
    @IBOutlet private var view2: UIView!

    // Initializers
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // Type Methods
    static func makeViewController() -> TestViewController {
        return TestViewController()
    }

    // Life-Cycle Methods
    override func viewDidLoad() {
        super.viewDidLoad()

        view1.setNeedsLayout()
        view1.layoutIfNeeded()
        hasLayoutedView1 = true
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        view2.setNeedsLayout()
        view2.layoutIfNeeded()
        hasLayoutedView2 = true
    }

    // IBActions
    @IBAction func goNextButtonPressed() {
        goToNextVc()
        delegate?.didPressTrackedButton()
    }

    @objc
    func goToRandomVcButtonPressed() {
        goToRandomVc()
    }

    // MARK: Other Methods
    func goToNextVc() { /* TODO */ }

    func goToInfoVc() { /* TODO */ }

    func goToRandomVc() {
        let viewCtrl = getRandomVc()
        present(viewCtrl, animated: true)
    }

    private func getRandomVc() -> UIViewController { return UIViewController() }

    // Subscripts
    subscript(_ someIndexThatIsNotEvenUsed: Int) -> String {
        get {
            return "This is just a test"
        }

        set {
            print("Just a test \(newValue)")
        }
    }
}

// Extensions
extension TestViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return UITableViewCell()
    }
}

First Where

コレクションでは.filter { }.firstより.first(where:)を使うべき。
https://realm.github.io/SwiftLint/first_where.html

first_where
// bad
myList.filter { $0 % 2 == 0 }.first

// good
myList.first(where: { $0 % 2 == 0 })
myList.first { $0 % 2 == 0 }

FlatMap over map and reduce

reduce([], +)が後に続くmapよりもflatMapを使うべき。
https://realm.github.io/SwiftLint/flatmap_over_map_reduce.html

flatmap_over_map_reduce
// bad
let foo = bar.map { $0.array }.reduce([], +)
 
// good
let foo = bar.flatMap { $0.array }

Force Unwrapping

強制アンラップは避けるべき。
https://realm.github.io/SwiftLint/force_unwrapping.html

force_unwrapping
// bad
let url = NSURL(string: query)!

// good
if let url = NSURL(string: query)

Function Default Parameter at End

関数でデフォルト値を持つ引数は後ろにまとめるべき。
https://realm.github.io/SwiftLint/function_default_parameter_at_end.html

function_default_parameter_at_end
// bad
func foo(y: Int = 0, x: String, z: CGFloat = 0) { }

// good
func foo(x: String, y: Int = 0, z: CGFloat = 0) { }

IBInspectable in Extension

extensionには@IBInspectableプロパティを追加すべきではない。
https://realm.github.io/SwiftLint/ibinspectable_in_extension.html

ibinspectable_in_extension
// bad
extension Foo {
  @IBInspectable private var x: Int
}

// good
class Foo {
  @IBInspectable private var x: Int
}

Identical Operands

同一のオペランドを比較するのは間違っている可能性がある。
https://realm.github.io/SwiftLint/identical_operands.html

identical_operands
// bad
1 == 1
foo == foo

// good
1 == 2
foo == bar

Implicit Return

クロージャ、関数、ゲッターでは暗黙的なリターンを使うべき。
https://realm.github.io/SwiftLint/implicit_return.html

implicit_return
// bad
foo.map {
    return $0 + 1
}

func foo() -> Int {
    return 0
}

class Foo {
    var bar: Int {
        get {
            return 0
        }
    }
}

// good
foo.map { $0 + 1 }

func foo() -> Int {
    0
}

class Foo {
    var bar: Int {
        get {
            0
        }
    }
}

Implicitly Unwrapped Optional

暗黙的にアンラップされているオプショナル型は可能な限り使うべきではない。
https://realm.github.io/SwiftLint/implicitly_unwrapped_optional.html

implicitly_unwrapped_optional
// bad
var int: Int! = 42 
let label: UILabel!

// good
let int: Int? = 42
@IBOutlet var label: UILabel!

Indentation Width

1つのタブまたは設定したスペースの量でコードをインデントすべき。
https://realm.github.io/SwiftLint/indentation_width.html

indentation_width
// bad
firstLine
        secondLine

// good
firstLine
    secondLine

Joined Default Parameter

デフォルトの区切り文字は明示的に使うべきではない。
https://realm.github.io/SwiftLint/joined_default_parameter.html

joined_default_parameter
// bad
let foo = bar.joined(separator: "")

// good
let foo = bar.joined()
let foo = bar.joined(separator: ",")

Last Where

コレクションでは.filter { }.lastより.last(where:)を使うべき。
https://realm.github.io/SwiftLint/last_where.html

last_where
// bad
myList.filter { $0 % 2 == 0 }.last

// good
myList.last(where: { $0 % 2 == 0 })

Legacy Multiple

剰余演算子%を使うよりisMultiple(of:)を使うべき。
https://realm.github.io/SwiftLint/legacy_multiple.html

legacy_multiple
// bad
let constant = 56
let isMultiple = value % constant == 0

// good
let constant = 56
let isMultiple = value.isMultiple(of: constant)

Legacy Objective-C Reference Type

bridgeされたObjective-Cの参照型よりSwiftの値型を使うべき。
https://realm.github.io/SwiftLint/legacy_objc_type.html

legacy_objc_type
// bad
var array = NSArray()
var calendar: NSCalendar? = nil
 
// good
var array = Array<Int>()
var calendar: Calendar? = nil

Legacy Random

従来の関数よりtype.random(in:)を使うべき。
https://realm.github.io/SwiftLint/legacy_random.html

legacy_random
// bad
arc4random(10)
arc4random_uniform(83)
drand48(52)

// good
Int.random(in: 0..<10)
Double.random(in: 8.6...111.34)
Float.random(in: 0..<1)

Variable Declaration Whitespace

letvarは他のステートメントと空白行で区切るべき。
https://realm.github.io/SwiftLint/let_var_whitespace.html

let_var_whitespace
// bad
let a = 0
var x = 1
x = 2

// good
let a = 0
var x = 1

x = 2

Literal Expression End Indentation

配列とdictionaryのリテラルの末尾は、開始した行と同じインデントにするべき。
https://realm.github.io/SwiftLint/literal_expression_end_indentation.html

literal_expression_end_indentation
// bad
let x = [
   1,
   2
   ]
   
    let x = [
       1,
       2
]

let x = [
   key: value
   ]

// good
[1, 2, 3]

[1,
 2
]

[
   1,
   2
]

   let x = [
       1,
       2
   ]

Lower ACL than parent

定義のアクセス制御レベルは、親と同じか低くするべき。
https://realm.github.io/SwiftLint/lower_acl_than_parent.html

lower_acl_than_parent
// bad
struct Foo { public func bar() {} }

// good
public struct Foo { public func bar() {} }

Missing Docs

宣言はドキュメント化するべき。
https://realm.github.io/SwiftLint/missing_docs.html

missing_docs
// good

/// docs
public class A {
    /// docs
    public func b() {}
}
/// docs
public class B: A { override public func b() {} }

/// docs
public class B: NSObject {
    // オーバーライドメソッドはOK
    override public var description: String { fatalError() } }

    /// docs
    public class A {
        deinit {}
    }
}

Modifier Order

修飾子の順序は一貫しているべき。
https://realm.github.io/SwiftLint/modifier_order.html

modifier_order
// bad
public class Foo {
   static public let bar = 42
}
 
// good
public class Foo {
   public static let bar = 42
}

Multiline Arguments

引数は同じ行に置くか、1行に1つずつ指定すべき。
https://realm.github.io/SwiftLint/multiline_arguments.html

multiline_arguments
// bad
foo(0,
    param1: 1, param2: true, param3: [3])
foo(0, param1: 1,
    param2: true, param3: [3])
 
// good
foo(0)
foo(param1: 1, param2: true) { }
foo(param1: 1,
    param2: true,
    param3: [3])

Multiline Arguments Brackets

複数行の引数には、新しい行に括弧をつけるべき。
https://realm.github.io/SwiftLint/multiline_arguments_brackets.html

multiline_arguments_brackets
// bad
foo(param1: "Param1", param2: "Param2",
         param3: "Param3"
)
foo(
    param1: "Param1",
    param2: "Param2",
    param3: "Param3")
foo(bar(
    x: 5,
    y: 7
)
)
 
// good
foo(param1: "Param1", param2: "Param2", param3: "Param3")
foo(
    param1: "Param1", param2: "Param2", param3: "Param3"
)
func foo(
    param1: "Param1",
    param2: "Param2",
    param3: "Param3"
)

Multiline Function Chains

関数を連鎖的に呼び出す場合、同じ行で呼び出すか、1行に1つずつ呼び出すべき。
https://realm.github.io/SwiftLint/multiline_function_chains.html

multiline_function_chains
// bad
let evenSquaresSum = [20, 17, 35, 4]
    .filter { $0 % 2 == 0 }.map { $0 * $0 }
    .reduce(0, +)

let evenSquaresSum = a.b(1, 2, 3)
    .c { blah in
        print(blah)
    }.d()
 
// good
let evenSquaresSum = [20, 17, 35, 4].filter { $0 % 2 == 0 }.map { $0 * $0 }.reduce(0, +)

let evenSquaresSum = [20, 17, 35, 4]
    .filter { $0 % 2 == 0 }.map { $0 * $0 }.reduce(0, +)",

let chain = a
    .b(1, 2, 3)
    .c { blah in
        print(blah)
    }
    .d()

Multiline Literal Brackets

複数行のリテラルの場合、新しい行に括弧をつけるべき。
https://realm.github.io/SwiftLint/multiline_literal_brackets.html

multiline_literal_brackets
// bad
let trio = ["harry",
            "ronald",
            "hermione"
]
let houseCup = ["gryffinder": 460, "hufflepuff": 370,
                "ravenclaw": 410, "slytherin": 450
]
 
// good
let trio = ["harry", "ronald", "hermione"]
let trio = [
    "harry",
    "ronald",
    "hermione"
]

Multiline Parameters

関数とメソッドの引数は、同じ行におくか、1行に1つずつ指定するべき。
https://realm.github.io/SwiftLint/multiline_parameters.html

multiline_parameters
// bad
func foo(param1: Int, param2: Bool,
         param3: [String]) { }

// good
func foo(param1: Int, param2: Bool) { }
func foo(param1: Int,
         param2: Bool,
         param3: [String]) { }

Multiline Parameters Brackets

複数行の引数は、新しい行に括弧をつけるべき。
https://realm.github.io/SwiftLint/multiline_parameters_brackets.html

multiline_parameters_brackets
// bad
func foo(param1: String, param2: String,
         param3: String
)

func foo(
    param1: String,
    param2: String,
    param3: String)
 
// good
func foo(param1: String, param2: String, param3: String)

func foo(
    param1: String, param2: String, param3: String
)

func foo(
    param1: String,
    param2: String,
    param3: String
)

Nimble Operator

フリーのmatcher関数より、Nimble演算子のオーバーロードを使うべき。
https://realm.github.io/SwiftLint/nimble_operator.html

nimble_operator
// bad
expect(seagull.squawk).to(equal("Hi"))
expect(seagull.squawk).toNot(equal("Hi"))
expect(10).to(beGreaterThan(2))

// good
expect(seagull.squawk) == "Hi!"
expect(seagull.squawk) != "Hi!"
expect(10) > 2

No Extension Access Modifier

extensionにアクセス修飾子をつけるべきではない。
https://realm.github.io/SwiftLint/no_extension_access_modifier.html

no_extension_access_modifier
// bad
private extension String {}
 
// good
extension String {}

No Grouping Extension

同じソースファイル内のコードをグループ化するためにextensionを使用すべきではない。
https://realm.github.io/SwiftLint/no_grouping_extension.html

no_grouping_extension
// bad
enum Fruit {}
extension Fruit {}

struct Tea {}
extension Tea: Error {}
 
// good
// プロトコルのデフォルト実装はOK
protocol Food {}
extension Food {}

NSLocalizedString Key

genstringsが機能するためには、NSLocalizedStringのkeyとして静的文字列を使うべき。
https://realm.github.io/SwiftLint/nslocalizedstring_key.html

nslocalizedstring_key
// bad
NSLocalizedString(method(), comment: "")
NSLocalizedString("key_\(param)", comment: "")
 
// good
NSLocalizedString("key", comment: "")
NSLocalizedString("key" + "2", comment: "")

NSLocalizedString Require Bundle

NSLocalizedStringの呼び出しは、文字列ファイルを含むバンドルを指定する必要がある。
https://realm.github.io/SwiftLint/nslocalizedstring_require_bundle.html

nslocalizedstring_require_bundle
// bad
NSLocalizedString("someKey", comment: "test")
NSLocalizedString("someKey", tableName: "a", comment: "test")
NSLocalizedString("someKey", tableName: "xyz",
                  value: "test", comment: "test")

// good
NSLocalizedString("someKey", bundle: .main, comment: "test")
NSLocalizedString("someKey", tableName: "a",
                  bundle: Bundle(for: A.self),
                  comment: "test")
NSLocalizedString("someKey", tableName: "xyz",
                  bundle: someBundle, value: "test"
                  comment: "test")

Number Separator

_は十進数で千の区切り文字として使うべき。
https://realm.github.io/SwiftLint/number_separator.html

number_separator
// bad
let foo = -10_0
let foo = -1000
 
// good
let foo = -1_000
let foo = -1_000_000
let foo = -1.000_1

Object Literal

画像や色はイニシャライザよりもオブジェクトリテラルを使うべき。
https://realm.github.io/SwiftLint/object_literal.html

object_literal
// bad
let image = UIImage(named: "foo")
let color = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
 
// good
let image = #imageLiteral(resourceName: "image.jpg")
let color = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)

Operator Usage Whitespace

演算子を使用するときは、演算子をスペースで囲むべき。
https://realm.github.io/SwiftLint/operator_usage_whitespace.html

operator_usage_whitespace
// bad
let foo =1+2
let foo = 1   > 2

// good
let foo = 1 + 2
let foo = 1 > 2

Optional Enum Case Match

?のないオプショナルの列挙型に対する、列挙型のケースの一致は、Swift5.1以降でサポートされる。
(Swift5.1以降を使用してない場合はこの方法は使用できない。)
https://realm.github.io/SwiftLint/optional_enum_case_matching.html

optional_enum_case_matching
// bad
switch foo {
 case .bar?: break
 case .baz: break
 default: break
}

// good
switch foo {
 case .bar: break
 case .baz: break
 default: break
}

Overridden methods call super

一部のオーバーライドメソッドは、常にsuperを呼び出す必要がある。
https://realm.github.io/SwiftLint/overridden_super_call.html

overridden_super_call
// bad
class VC: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        //Not calling to super
        self.method()
    }
}

class VC: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        //Other code
        super.viewWillAppear(animated)
    }
}

class VC: UIViewController {
    override func didReceiveMemoryWarning() {
    }
}
 
// good
class VC: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
}

class VC: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        self.method1()
        super.viewWillAppear(animated)
        self.method2()
    }
}

class VC: UIViewController {
    override func loadView() {
    }
}

class Some {
    func viewWillAppear(_ animated: Bool) {
    }
}

class VC: UIViewController {
    override func viewDidLoad() {
    defer {
        super.viewDidLoad()
        }
    }
}

Override in Extension

extensionでは定義をoverrideすべきではない。
https://realm.github.io/SwiftLint/override_in_extension.html

override_in_extension
// bad
extension Person {
  override var age: Int { return 42 }
}

extension Person {
  override func celebrateBirthday() {}
}
 
// good
extension Person {
  var age: Int { return 42 }
}

extension Person {
  func celebrateBirthday() {}
}

Pattern Matching Keywords

キーワードをタプルの外に出し、複数のパターンマッチングバインディングを組み合わせるべき。
https://realm.github.io/SwiftLint/pattern_matching_keywords.html

pattern_matching_keywords
// bad
switch foo {
    case (let x, let y): break
}

// good
switch foo {
    case let (x, y): break
}

Prefer Nimble

XCTAssert関数よりNimbleマッチャーを使うべき。
https://realm.github.io/SwiftLint/prefer_nimble.html

prefer_nimble
// bad
XCTAssertTrue(foo)
XCTAssertEqual(foo, 2)

// good
expect(foo) == 1
expect(foo).to(equal(1))

Prefer Self Type Over Type of Self

プロパティにアクセスするときや、メソッドを呼び出すときは、type(of: self)よりSelfを使うべき。
https://realm.github.io/SwiftLint/prefer_self_type_over_type_of_self.html

prefer_self_type_over_type_of_self
// bad
class Foo {
    func bar() {
        type(of: self).baz()
    }
}

// good
class Foo {
    func bar() {
        Self.baz()
    }
}

Prefer Zero Over Explicit Init

パラメータが0の明示的な初期化(例:CGPoint(x: 0, y: 0))より.zeroを使うべき。
https://realm.github.io/SwiftLint/prefer_zero_over_explicit_init.html

prefer_zero_over_explicit_init
// bad
CGPoint(x: 0, y: 0)

// good
CGPoint.zero

Prefixed Top-Level Constant

最上位の定数には、定数名の先頭にkをつけるべき。
https://realm.github.io/SwiftLint/prefixed_toplevel_constant.html

prefixed_toplevel_constant
// bad
private let foo = 20.0

// good
private let kFoo = 20.0

Private Actions

@IBActionprivateにすべき。
https://realm.github.io/SwiftLint/private_action.html

private_action
// bad
@IBAction func barButtonTapped(_ sender: UIButton) {}

// good
@IBAction private func barButtonTapped(_ sender: UIButton) {}

Private Outlets

@IBOutletprivateにすべき。(上位レイヤーにUIKitが漏洩するのを防ぐため)
https://realm.github.io/SwiftLint/private_outlet.html

private_outlet
// bad
@IBOutlet var label: UILabel?

// good
@IBOutlet private var label: UILabel?

Private Combine Subject

Combine Subjectはprivateにするべき。
https://realm.github.io/SwiftLint/private_subject.html

private_subject
// bad
final class Foobar {
    let goodSubject = PassthroughSubject<Bool, Never>()
}
 
// good
final class Foobar {
    private let goodSubject = PassthroughSubject<Bool, Never>()
}

Prohibited Interface Builder

IB(InterfaceBuilder)を使ってViewを生成するのは避けるべき。
https://realm.github.io/SwiftLint/prohibited_interface_builder.html

prohibited_interface_builder
// bad
class ViewController: UIViewController {
    @IBOutlet var label: UILabel!
    @IBAction func buttonTapped(_ sender: UIButton) {}
}
 
// good
class ViewController: UIViewController {
    var label: UILabel!
    @objc func buttonTapped(_ sender: UIButton) {}
}

Prohibited calls to super

一部のメソッドはsuper(親クラスのメソッド)を呼び出すべきではない。
https://realm.github.io/SwiftLint/prohibited_super_call.html

prohibited_super_call
// bad
class VC: UIViewController {
    override func loadView() {
        super.loadView()
    }
}

Quick Discouraged Call

describecontext内で推奨されない呼び出し。
https://realm.github.io/SwiftLint/quick_discouraged_call.html

quick_discouraged_call
// bad
class TotoTests: QuickSpec {
   override func spec() {
       describe("foo") {
           let foo = Foo()
       }
   }
}

// good
class TotoTests: QuickSpec {
   override func spec() {
       describe("foo") {
           beforeEach {
               let foo = Foo()
               foo.toto()
           }
       }
   }
}

Quick Discouraged Focused Test

一部のみ有効となるテストは実行すべきではない。
https://realm.github.io/SwiftLint/quick_discouraged_focused_test.html

quick_discouraged_focused_test
class TotoTests: QuickSpec {
    override func spec() {
        // bad
        fdescribe("foo") { }
        fcontext("foo") { }
        fit("foo") { }
        fitBehavesLike("foo")

        // good
        describe("foo") { }
        context("foo") { }
        it("foo") { }
        itBehavesLike("foo")
    }
}

Quick Discouraged Pending Test

一部のみ無効となるテストは実行すべきではない。
https://realm.github.io/SwiftLint/quick_discouraged_pending_test.html

quick_discouraged_pending_test
class TotoTests: QuickSpec {
    override func spec() {
        // bad
        xdescribe("foo") { }
        xcontext("foo") { }
        xit("foo") { }
        pending("foo")
        xitBehavesLike("foo")

        // good
        describe("foo") { }
        context("foo") { }
        it("foo") { }
        itBehavesLike("foo")
    }
}

Raw Value For Camel Cased Codable Enum

CodableStringを継承した列挙型のCamelケースの場合は値を持つべき。
https://realm.github.io/SwiftLint/raw_value_for_camel_cased_codable_enum.html

raw_value_for_camel_cased_codable_enum
// bad
enum Status: String, Codable {
    case ok
    case notAcceptable
    case maybeAcceptable = "maybe_acceptable"
}
 
// good
enum Status: String, Codable {
    case ok
    case notAcceptable = "not_acceptable"
    case maybeAcceptable = "maybe_acceptable"
}

Reduce Into

copy-on-writeの場合、reduce(_:_:)よりreduce(into:_:)を使うべき。
https://realm.github.io/SwiftLint/reduce_into.html

reduce_into
// bad
let bar = values.reduce("abc") { $0 + "\($1)" }

// good
let foo = values.reduce(into: "abc") { $0 += "\($1)" }

Redundant Nil Coalescing

??演算子は、左辺がnilの場合のみ評価されるため、右辺にnilを記述するのは冗長。
https://realm.github.io/SwiftLint/redundant_nil_coalescing.html

redundant_nil_coalescing
// bad
var myVar: Int? = nil
myVar ?? nil
 
// good
var myVar: Int?
myVar ?? 0

Redundant Type Annotation

変数に冗長な型アノテーションをつけてはいけない。
https://realm.github.io/SwiftLint/redundant_type_annotation.html

redundant_type_annotation
// bad
var url:URL = URL()
var isEnabled: Bool = true
 
// good
var url = URL()
var url: CustomStringConvertible = URL()

Required Deinit

クラスにはdeinitメソッドを明示的に持つべき。
https://realm.github.io/SwiftLint/required_deinit.html

required_deinit
// bad
class Apple { }

// good
class Apple {
    deinit { }
}

Required Enum Case

特定のプロトコルに準拠する列挙型は、特定のケースを実装するべき。
https://realm.github.io/SwiftLint/required_enum_case.html

required_enum_case
// bad
enum MyNetworkResponse: String, NetworkResponsable {
    case success, error
}

// good
enum MyNetworkResponse: String, NetworkResponsable {
    case success, error, notConnected
}

enum MyNetworkResponse: String, NetworkResponsable {
    case success, error, notConnected(error: Error)
}

Single Test Class

テストファイルには、単一のQuickSpecまたはXCTestCaseクラスを含むべき(複数含むべきではない)
https://realm.github.io/SwiftLint/single_test_class.html

single_test_class
// bad
class FooTests: QuickSpec {  }
class BarTests: QuickSpec {  }

class FooTests: XCTestCase {  }
class BarTests: XCTestCase {  }

class FooTests: QuickSpec {  }
class BarTests: XCTestCase {  }
 
// good
class FooTests: QuickSpec {  }

class FooTests: XCTestCase {  }

Min or Max over Sorted First or Last

sorted().firstsorted().lastよりmin()max()を使うべき。
https://realm.github.io/SwiftLint/sorted_first_last.html

sorted_first_last
// bad
myList.sorted().first
myList.sorted().last
 
// good
let min = myList.min()
let max = myList.max()

Sorted Imports

import文はソートされるべき。
https://realm.github.io/SwiftLint/sorted_imports.html

sorted_imports
// bad
import AAA
import ZZZ
import BBB
import CCC
 
// good
import AAA
import BBB
import CCC
import DDD

Static Operator

演算子は、自由関数ではなく静的関数として定義すべき。
https://realm.github.io/SwiftLint/static_operator.html

static_operator
// bad
func == (lhs: A, rhs: A) -> Bool {
  return false
}
func == <T>(lhs: A<T>, rhs: A<T>) -> Bool {
  return false
}
 
// good
class A: Equatable {
  static func == (lhs: A, rhs: A) -> Bool {
    return false
  }
}

class A<T>: Equatable {
    static func == <T>(lhs: A<T>, rhs: A<T>) -> Bool {
        return false
    }
}

Strict fileprivate

fileprivateは避けるべき。
https://realm.github.io/SwiftLint/strict_fileprivate.html

strict_fileprivate
// bad
class MyClass {
  fileprivate let myInt = 4
}

// good
class MyClass {
  private let myInt = 4
}

Strong IBOutlet

@IBOutletweakで定義すべきではない。
https://realm.github.io/SwiftLint/strong_iboutlet.html

strong_iboutlet
// bad
class ViewController: UIViewController {
    @IBOutlet weak var label: UILabel?
}

// good
class ViewController: UIViewController {
    @IBOutlet var label: UILabel?
}

Switch Case on Newline

switch文内のcaseは常に改行すべき。
https://realm.github.io/SwiftLint/switch_case_on_newline.html

switch_case_on_newline
// bad
switch foo {
    case 1: return true
}

// good
switch foo {
    case 1: 
 return true
}

Test case accessibility

テストケースには、privateの非テストメンバーのみ含めるべき。
https://realm.github.io/SwiftLint/test_case_accessibility.html

test_case_accessibility
// bad
class FooTests: XCTestCase {
    var foo: String?
    let bar: String?

    static func foo() {}

    func setUp(withParam: String) {}

    func foobar() {}

    func not_testBar() {}

    enum Nested {}

    static func testFoo() {}

    static func allTests() {}

    func testFoo(hasParam: Bool) {}
}

// good
let foo: String?

class FooTests: XCTestCase {
    static let allTests: [String] = []

    private let foo: String {
        let nestedMember = "hi"
        return nestedMember
    }

    override static func setUp() {
        super.setUp()
    }

    override func setUp() {
        super.setUp()
    }

    override func setUpWithError() throws {
        try super.setUpWithError()
    }

    override static func tearDown() {
        super.tearDown()
    }

    override func tearDown() {
        super.tearDown()
    }

    override func tearDownWithError() {
        try super.tearDownWithError()
    }

    override func someFutureXCTestFunction() {
        super.someFutureXCTestFunction()
    }

    func testFoo() {
        XCTAssertTrue(true)
    }

    func testBar() {
        func nestedFunc() {}
    }

    private someFunc(hasParam: Bool) {}
}

Toggle Bool

someBool = !someBool.よりsomeBool.toggle()を使うべき。
https://realm.github.io/SwiftLint/toggle_bool.html

toggle_bool
// bad
isHidden = !isHidden

// good
isHidden.toggle()

Trailing Closure

可能な限り、トレイリングクロージャを使うべき。
https://realm.github.io/SwiftLint/trailing_closure.html

trailing_closure
// bad
foo.map({ $0 + 1 })

// good
foo.map { $0 + 1 }

Type Contents Order

型内のサブクラス、プロパティ、メソッドの定義順は従うべき。
https://realm.github.io/SwiftLint/type_contents_order.html

type_contents_order
// bad
class TestViewController: UIViewController {
    // Subtypes
    class TestClass {
        // 10 lines
    }

    // Type Aliases
    typealias CompletionHandler = ((TestEnum) -> Void)
}
class TestViewController: UIViewController {
    // Stored Type Properties
    static let cellIdentifier: String = "AmazingCell"

    // Subtypes
    class TestClass {
        // 10 lines
    }
}

class TestViewController: UIViewController {
    // Stored Instance Properties
    var shouldLayoutView1: Bool!

    // Stored Type Properties
    static let cellIdentifier: String = "AmazingCell"
}
 
// good
class TestViewController: UIViewController {
    // Type Aliases
    typealias CompletionHandler = ((TestEnum) -> Void)

    // Subtypes
    class TestClass {
        // 10 lines
    }

    struct TestStruct {
        // 3 lines
    }

    enum TestEnum {
        // 5 lines
    }

    // Type Properties
    static let cellIdentifier: String = "AmazingCell"

    // Instance Properties
    var shouldLayoutView1: Bool!
    weak var delegate: TestViewControllerDelegate?
    private var hasLayoutedView1: Bool = false
    private var hasLayoutedView2: Bool = false

    private var hasAnyLayoutedView: Bool {
         return hasLayoutedView1 || hasLayoutedView2
    }

    // IBOutlets
    @IBOutlet private var view1: UIView!
    @IBOutlet private var view2: UIView!

    // Initializers
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // Type Methods
    static func makeViewController() -> TestViewController {
        // some code
    }

    // View Life-Cycle Methods
    override func viewDidLoad() {
        super.viewDidLoad()

        view1.setNeedsLayout()
        view1.layoutIfNeeded()
        hasLayoutedView1 = true
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        view2.setNeedsLayout()
        view2.layoutIfNeeded()
        hasLayoutedView2 = true
    }

    // IBActions
    @IBAction func goNextButtonPressed() {
        goToNextVc()
        delegate?.didPressTrackedButton()
    }

    // Other Methods
    func goToNextVc() { /* TODO */ }

    func goToInfoVc() { /* TODO */ }

    func goToRandomVc() {
        let viewCtrl = getRandomVc()
        present(viewCtrl, animated: true)
    }

    private func getRandomVc() -> UIViewController { return UIViewController() }

    // Subscripts
    subscript(_ someIndexThatIsNotEvenUsed: Int) -> String {
        get {
            return "This is just a test"
        }

        set {
            log.warning("Just a test", newValue)
        }
    }

    deinit {
        log.debug("deinit")
    },
}

Unavailable Function

未実装の関数は使用不可としてマークするべき。
https://realm.github.io/SwiftLint/unavailable_function.html

unavailable_function
// bad
class ViewController: UIViewController {
    public required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

// good
class ViewController: UIViewController {
    @available(*, unavailable)
    public required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Unneeded Parentheses in Closure Argument

クロージャの引数を定義するとき、括弧は必要ない。
https://realm.github.io/SwiftLint/unneeded_parentheses_in_closure_argument.html

unneeded_parentheses_in_closure_argument
// bad
let foo = { (bar) -> Bool in
   return true 
}
 
// good
let foo = { bar -> Bool in
   return true 
}

Unowned Variable Capture

クラッシュの可能性を回避するため、弱参照にしてキャプチャするべき。
https://realm.github.io/SwiftLint/unowned_variable_capture.html

unowned_variable_capture
// bad
foo { [unowned self] in _ }
foo { [unowned bar] in _ }
foo { [bar, unowned self] in _ }
 
// good
foo { [weak self] in _ }
foo { [weak self] param in _ }
foo { [weak bar] in _ }
foo { [weak bar] param in _ }

Untyped Error in Catch

catchで、型キャストなしのエラー変数を定義すべきではない。
https://realm.github.io/SwiftLint/untyped_error_in_catch.html

untyped_error_in_catch
// bad
do {
  try foo()
} catch var error {}

// good
do {
  try foo()
} catch let error as MyError {
} catch {}

Unused Declaration

定義は少なくとも1回は全てのファイル内のどこかで参照されるべき。
https://realm.github.io/SwiftLint/unused_declaration.html

unused_declaration
// bad
let foo = 0
 
// good
let foo = 0
_ = foo

Unused Import

importされた全てのモジュールが、ファイルをコンパイルするために必要とされるべき。
https://realm.github.io/SwiftLint/unused_import.html

unused_import
// bad
import Foundation
class A { }

// good
import Foundation
@objc
class A { }

Vertical Parameter Alignment On Call

関数を呼び出す時に、パラメータが複数行にまたがる場合は垂直に揃えるべき。
https://realm.github.io/SwiftLint/vertical_parameter_alignment_on_call.html

vertical_parameter_alignment_on_call
// bad
foo(param1: 1, param2: bar
                param3: false, param4: true)

foo(param1: 1, param2: bar
 param3: false, param4: true)

foo(param1: 1, param2: bar
       param3: false,
       param4: true)
 
// good
foo(param1: 1, param2: bar
    param3: false, param4: true)

foo(param1: 1, param2: bar)

foo(param1: 1, param2: bar
    param3: false,
    param4: true)

Vertical Whitespace Between Cases

switch文内のcasecaseの間は空白行を1行含むべき。
https://realm.github.io/SwiftLint/vertical_whitespace_between_cases.html

vertical_whitespace_between_cases
// bad
switch x {
    case .valid:
        print("x is valid")
    case .invalid:
        print("x is invalid")
}
 
// good
switch x {
    case .valid:
        print("x is valid")

    case .invalid:
        print("x is invalid")
}

Vertical Whitespace before Closing Braces

中括弧を閉じる前に空白行を入れるべきではない。
https://realm.github.io/SwiftLint/vertical_whitespace_closing_braces.html

vertical_whitespace_closing_braces
// bad
[
1,
2,
3

] 

do {
  print("x is 5")

}

// good
[
1,
2,
3
] 

do {
  print("x is 5")
}

Vertical Whitespace after Opening Braces

中括弧を開いた後に空白行を入れるべきではない。
https://realm.github.io/SwiftLint/vertical_whitespace_opening_braces.html

vertical_whitespace_opening_braces
// bad
[

1,
2,
3
] 

do {

  print("x is 5")

}

// good
[
1,
2,
3
] 

do {
  print("x is 5")
}

XCTest Specific Matcher

XCTAssertEqualXCTAssertNotEqualより、特定のXCTestマッチャーを使うべき。
https://realm.github.io/SwiftLint/xct_specific_matcher.html

xct_specific_matcher
// bad
XCTAssertEqual(foo, true)
XCTAssertEqual(foo, false)
XCTAssertEqual(foo, nil)
XCTAssertNotEqual(foo, true)
XCTAssertNotEqual(foo, false)

// good
XCTAssertFalse(foo)
XCTAssertTrue(foo)
XCTAssertNil(foo)
XCTAssertNotNil(foo)
XCTAssertEqual(foo, 2)
XCTAssertNotEqual(foo, "false")

Yoda condition rule

変数は比較演算子の左側に配置し、定数は右側に配置すべき。
https://realm.github.io/SwiftLint/yoda_condition.html

yoda_condition
// bad
if 42 == foo {}

// good
if foo == 42 {}

おわりに

こうして全体的にルールを見てみると、Opt-inのルールにも意外と使えそうというかDefault(有効)になってていいと思うルールも結構ありました。Conditional Returns on Newline(guardのreturnは改行すべきというルール)などについてはよく論争が起きている気がするので、チーム全体で吟味して有効/無効にしても良さそうだなと特に思います。
全ルールをまとめてみると「こういう書き方もあるんだな」って気づきがあるのでおすすめです。(因みにまとめるのに数日かかりました。)

参考

こちら参考にさせていただきました🙇‍♂️

15
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?