2015年6月29日月曜日

Swift2から新たに導入されたguardステートメントの用途について(Swift2, iOS9)

Swift2/iOS9から新たにguardステートメントが導入されています。guardステートメントはifステートメントと似ていますが、その本質的な所はまったく異なる様です。guardステートメントの特徴を述べると以下のようになるでしょう。

  • エラー判定で使用することを想定しているよ
  • ついでにアンラップもしちゃうよ
  • 可読性上がったよね
という所ではないでしょうか。一見、ifステートメントと違いがなさそうですが、可読性の観点から見るとその性質が異なっている事が分かると思います。
エラー判定で使用することを想定している

guradステートメントでは、必ずreturn, break, continue, throwを使用して現在のスコープを抜けるか、@noreturn属性のついたメソッドを呼び出す必要があります。つまり、これは想定しない値を受信して処理続行不可能な場合に現在の処理を抜けたり、現在の値を諦めて次の値を参照する必要がある場合に使用することを想定していると考えられます。@noreturn属性のメソッドとは呼び元に戻ってこないメソッドの事で、fatalError()の様にプログラムを終了するようなメソッドの事を指しています。

単純なguardステートメントの例
func guardExample1(ex1: Int32?) {
    guard var value = ex1 else {
        // error
        return
    }
    print("value: \(value)")
}
guardExample1(1)    // value: 1
ループ中guardステートメントの使用例
func guardExample2(ex2: [Int32?]) {
    var counter = ex2.count - 1
    
    while counter >= 0 {
        guard let value = ex2[counter--] else {
            continue
        }
        print("value: \(value)")
    }
}
guardExample2([1, 2, 3, nil, 5])
// value: 5
// value: 3
// value: 2
// value: 1
ついでにアンラップもしちゃうよ

ifステートメントと同様ににguardステートメントでもアンラップする事ができます。ifステートメントでは、そのスコープ内でのみアンラップした変数を使用する事が出来ますが、guardステートメントでは、スコープの外側、つまりguardステートメントと同列のスコープでも使用可能な所が一番の特徴になるでしょう。

guardステートメントのスコープ外でもアンラップした変数にアクセスが可能。
func guardExample3(ex1: String?, ex2: String?) {
    guard let e1 = ex1 else {
        // error
        return
    }
    
    guard let e2 = ex2 else {
        // error
        return
    }
    
    print("ex1 = \(e1)")
    print("ex2 = \(e2)")
    
}
guardExample3("a", ex2: "B")
可読性上がったよね

guardステートメントによる一目で分かるエラーの明確化及び、アンラップ時のスコープの拡大は小さい様で可読性への貢献は大きいのではないでしょうか。

2つの変数をguardステートメントでアンラップした場合と、ifステートメントでアンラップした場合のネストの違い。明らかにguardステートメントの方が可読性が高い。
func guardExample3(ex1: String?, ex2: String?) {
    guard let e1 = ex1 else {
        // error
        return
    }
    
    guard let e2 = ex2 else {
        // error
        return
    }

    // do something to do
    print("ex1 = \(e1), ex2 = \(e2)")
}
guardExample3("a", ex2: "B")


func guardExample4(ex1: String?, ex2: String?) {
    if let e1 = ex1 {
        if let e2 = ex2 {
            // something to do
            print("ex1 = \(e1), ex2 = \(e2)")
        }
    }
}

guardExample4("a", ex2: "b")
参考:The Swift Programming Language
詳細!Swift iPhoneアプリ開発 入門ノート Swift 1.1+Xcode 6.1+iOS 8.1対応
ソーテック社 (2014-12-12)
売り上げランキング: 3,900

0 件のコメント :

コメントを投稿