【Swift】コードをコンパクトに記述できるオプショナルチェーン(optional chaining)の性質と活用例

公開日: : 最終更新日:2016/02/10 iPhoneアプリ開発

20150108-113233.jpg

最近はSwiftでコーディングすることが多い@akio0911です。今日はSwiftでコードをコンパクトに記述できる「オプショナルチェーン」という仕組みについて紹介します!

    

スポンサード リンク

オプショナルチェーンの基本

オプショナル型なプロパティを持つ、以下の様なクラス群が定義されていたとします。

class A {
    var b:B?
}

class B {
    var c:C?
}

class C {
    var name:String = ""
    var age:Int = 0

    func isMale() -> Bool {
        return true
    }
    
    func display() {
        print("name = \(name), age = \(age)")
    }
}

    

そして、以下のようにオブジェクトを生成したとします。

var objectC = C()
objectC.name = "sato"
objectC.age = 35

var objectB = B()
objectB.c = objectC

var objectA:A? = A()
objectA!.b = objectB

    

ここでobjectCのnameプロパティにアクセスしたいとします。こんな時に活用できるのが「オプショナルチェーン (optional chaining, optional chain) 」です。

let n = objectA?.b?.c?.name

    

上記のコードは以下の様な動きをします。

  • objectA, b, c の全てがnilでは無い場合、定数nにはnameが代入される
  • objectA, b, c のいずれかがnilの場合、定数nはnilとなる

この時、定数nはnilになりえるので、その型はnameと同じString型ではなく、String?型(オプショナル)となります。

    

オプショナル束縛と組み合わせる

オプショナルチェーンは、以下のようにオプショナル束縛 (optional binding) と組み合わせて使うことができます。

if let name = objectA?.b?.c?.name {
    // objectA, b, c の全てがnilでは無い場合、ここが実行される
    println(name)
}

    

辞書へのアクセスにオプショナルチェーンを使ってみる

SwiftのDictionaryは、キーを指定してアクセスする際にオプショナル型が返ってくるので、以下のように記述することができます。

var dictionary = [String:C]()
dictionary["sato"] = objectC

if let name = dictionary["sato"]?.name {
    // dictionary["sato"] が存在する場合、ここが実行される
    println(name)
}

    

オプショナルチェーンでメソッドを呼び出す

オプショナルチェーンではメソッドも呼び出すことができますが、その場合はメソッドの返り値のオプショナル型が返ってきます。

例えば先程のCクラスで定義されているisMaleメソッドは返り値はBoolなので、このメソッドをオプショナルチェーン内で呼び出すとBool?となります。

// objectA, b, c の全てがnilではない時のみ、isMale()メソッドが呼び出される。
// isMale()の返り値はBool型なので、変数maleの型はBool?(オプショナル)となる。
let male = objectA?.b?.c?.isMale()

    

オプショナルチェーンでメソッドが呼び出されたかどうかをチェックする

オプショナル束縛 (optional binding) と組み合わせることで、isMale()メソッドが呼び出されたか否かによって処理を分岐させることができます。

if let male = objectA?.b?.c?.isMale() {
    println("isMale()が呼び出された")
}else{
    println("isMale()が呼び出されなかった")
}

    

オプショナルチェーンで返り値のないメソッドが呼び出されたかどうかをチェックする

Swiftでは返り値がないメソッドも実際には空タプル () を返すので、返り値がないメソッドをオプショナルチェーン内で呼び出した場合は空タプルのオプショナル ()? を返します。

// retの型は空タプルのオプショナル ()?
let ret = objectA?.b?.c?.display()

    

よって、このことを利用して、返り値がないメソッドが呼び出されたか否かをチェックすることができます。

if objectA?.b?.c?.display() != nil {
    println("display() が呼び出された")
}else{
    println("display() が呼び出されていない")
}

    

オプショナルチェーンを代入先として使う

オプショナルチェーンは、値の参照やメソッドの呼び出しだけでなく、代入先としても使用することができます。

// objectA, b, c の全てがnilでは無いときのみ、代入が実行される
objectA?.b?.c?.name = "suzuki"

    

また、この代入操作は空タプルのオプショナルを返します。よって以下のようにして代入が成功したか否かをチェックすることができます。

if (objectA?.b?.c?.name = "suzuki") != nil {
    println("代入できた")
}else{
    println("代入できなかった")
}

    

@akio0911はこう思った。

オプショナル束縛だけを使っているとコードが煩雑になりがちですが、今回紹介したオプショナルチェーンを使うことでかなりコードをコンパクトに記述できると思います。

    

ちなみにオプショナルチェーンについては以下の書籍が詳しかったです!

この記事が気に入ったら「いいね!」しよう

follow us in feedly

Feedlyで最新記事を購読

Twitterで更新情報をゲット!

LINEでご感想・ご要望お送りください!
(スマホでLINEを起動 > 友だち追加 > QRコード)

関連記事

I20160102-131507.jpg

Swift 2の文法が分かるオススメ本「詳解 Swift 改訂版」

Swift文法書の定番とも言える、荻原 剛志さんの「詳解 Swift」。 Swiftの文法をキ

記事を読む

20140810-193043.jpg

WordPressでObjective-Cのソースコードをキレイに整形して表示する方法

WordPressの記事内で、Objective-Cのソースコードをキレイに整形して表示する方法

記事を読む

20150409-103620.jpg

描いたベクターグラフィックをSwift/Objective-Cコードに変換できる「Paint Code 2」

引用元 : PaintCode ベクターグラフィックを描き、それを描画するためのSwift

記事を読む

20160807-113229.jpg

UITableViewのリサイズに合わせて一番下のセルを常に一番下に表示する方法

一番下のセルを表示している状態でUITableViewの下端を上に移動させると一番下のセルが隠れ

記事を読む

20160416-142928.jpg

Swift 2.2で可能になったタプルの比較を試してみる

Swift 2.2でタプルの比較が行えるようになったので、色々と試してみました。   

記事を読む

20160420-180135.jpg

【RxSwift】2つのUITextFieldに入力された数値の合計をUILabelに表示する

そろそろRxSwiftについて学び始めよう!ということで、まずは2つのUITex

記事を読む

I20160409-211651.jpg

Xcode 7.3の新機能についてまとめてみた

2016年3月22日にXcode 7.3がリリースされましたが、自分が知らない機能があるかもしれ

記事を読む

I20151030-214417.jpg

【開発本】SpriteKitの入門書籍「iPhoneのゲームアプリをつくろう!」

SwiftとSpriteKitでiPhoneゲームアプリを開発するための入門書「iPhone

記事を読む

20160730-172416.jpg

Auto Layoutで非表示にした部分を詰める(トルツメ)する方法

Auto Layoutを使って非表示にしたコントロールの部分を詰める(トルツメ)方法を説明します

記事を読む

I20160204-120840.jpg

Swiftでプロトコル型に対して===演算子を使いたい時の対処法

プロトコル型の変数や定数に対して===演算子を使うと「error: binary opera

記事を読む

PAGE TOP ↑