【いまさら聞けない】SwiftのOptionalってなに?

3bf6da1f63cd8b7a2f802f95c269ed80?s=47 FromAtom
June 23, 2017

 【いまさら聞けない】SwiftのOptionalってなに?

社内の勉強会で話しました

3bf6da1f63cd8b7a2f802f95c269ed80?s=128

FromAtom

June 23, 2017
Tweet

Transcript

  1. 4.

    はじめに Swift の Optional が複雑( に見える) のは、 同じ記号(! と ?

    ) が違う意 味で使われているから たとえば、 下記で使われる ! と ? はすべて意味が違います var a: Int? = 1 var b: Int! = 2 let c: Int = a! + 10 self?.collectionView?.reloadData()
  2. 7.

    Swift での nil とは nil について知らないと Optional を理解できない Swift のnil

    は値・ 式の評価結果がない( もしくはエラー) を表す Swift1.x 系では do-catch と throw が無かったんや Swift にはポインタがないので厳密には空ポインタではない
  3. 9.

    Optional Int Type まずは Int で考えます Int は整数型なので整数ではない nil は代入できない

    nil を代入したい場合はInt? という Optional Int Type を使う var a: Int = 0 var b: Int? = 0 a = nil // コンパイルエラー になる b = nil // 代入できる
  4. 10.

    Optional Int Type var a: Int = 0 var b:

    Int? = 0 var c: Optional<Int> = 0 // 上と同じ Int? はOptional<Int> のシンタックスシュガー Optional<T> というクラス( 正確には enum ) があり、Generics で様々 な型を入れられる つまり、 Int と Int? は別物 ← 超重要 型が違うので同じようには使えない ← 当たり前だよね
  5. 11.

    Optional Int Type を Int として使いたい Int? はInt ではないのでInt として扱えない

    Unwrap することで使えるようになる ここで "!" が登場します Xcode に言われるがまま修正すると入ってくる謎の "!" "!" を使って Unwrap することを Force Unwrap と言います
  6. 12.

    Force Unwrap var optionalValue: Int? = 2000 var a: Int

    = optionalValue + 20 // 型が違うのでコンパイルエラー になる var b: Int = optionalValue! + 20 // 2020 になる optionalValue! の "!" で Int を取り出している もしoptionalValue の中身がnil だったら実行時クラッシュ
  7. 13.

    条件判定 実行時クラッシュすると困るので条件判定をします var optionalValue: Int? = 2000 if optionalValue !=

    nil { print(optionalValue!) // ここでは "!" が必要 } if optionalValue == 1000 { // "!" を書かなくても良い print("1000 だよ") } else if optionalValue == 2000 { print("2000 だよ") // これが表示される }
  8. 14.

    Optional Binding 毎回 "!" 書くのは大変 if 文の then 節では nil

    チェックした変数を使いたいことが多い そこで Optional Binding です var optionalValue: Int? = 2000 if let value = optionalValue { // if-let で1 つの構文 print(value) //"!" が要らない } else { print("nil だったらしいよ") //optionalValue がnil なら実行される }
  9. 15.

    Optional Binding 複数の値を Optional Binding することもできます var optionalA: Int? =

    1 var optionalB: Int? = 2 if let a = optionalA, let b = optionalB { // optionalA, optionalB が両方nil ではないときにくる print(a + b) // 3 が表示される }
  10. 16.

    条件式との組み合わせ optional binding した値を条件式で使える var optionalValue: Int? = 2000 if

    let value = optionalValue, value > 100 { print("100 より大きいよ") }
  11. 17.

    Nil Coalescing Operator ある Optional Type の変数がnil だった時に、 他の定数を使いたいときに 便利なやつ

    let value: Int = optionalValue ?? 100 optionalValue がnil なら100 が代入されます。 便利だけど多用すると右 に長くなっていくので注意。 let value: Int = optA ?? optB ?? optC ?? 100 ※Bool 値を見ているわけではないので注意
  12. 19.

    Implicitly Unwrapped Optional 参照したら勝手に Unwrap してくれる Optional Type var a:

    Int = 0 var b: Int! = 0 a = nil // コンパイルエラー になる b = nil // 代入できる Int! はImplicitlyUnwrappedOptional<Int> のシンタックスシュガー var b: Int! = 0 var c: ImplicitlyUnwrappedOptional<Int> = 0 // 上と同じ
  13. 20.

    Implicitly Unwrapped Optional "!" で Unwrap しなくてもよい var a: Int!

    = 0 var b: Int = a + 20 // "!" マー クがなくてもアクセスできる! a = nil // a にnil をいれてみる var c: Int = a + 20 // 実行時にクラッシュする クラスの生成直後は nil だけど、1 度設定されたら nil になりえない変数に 使う。StoryBoard との関連(IBOutlet ) でよく使います。
  14. 23.

    Optional Chaining こういう class があり、3 世代前の名前を知りたい時 class Human { var

    ancestor: Human? var name: String } こうやれば取れるけど、 どこかで nil が入ったらクラッシュ print(human.ancestor!.ancestor!.ancestor!.name)
  15. 24.

    Optional Chaining これでもいけるけど、 if let a = human.ancestor, let b

    = a.ancestor, let c = b.ancestor { print(c.name) } Optional Chaining を使えばこう書ける if let name = human.ancestor?.ancestor?.ancestor?.name { print(name) }
  16. 26.

    ちょっと便利な Optional Chaining テク Void を返すメソッドを Optional Chaining で実行するとOptional<Void> を

    返すようになる。 if self?.collectionView?.reloadData() != nil { //reloadData() が呼ばれたら実行される } if (human.ancestor?.ancestor?.ancestor? = newAncestor) != nil { // 代入が成功したら実行される }
  17. 27.

    まとめ これで Swift コー ド上で使われる様々 な意味の "!" と "?" の違いが(

    ふわ っと) 分かったと思います。 var a: Int? = 1 // Optional var b: Int! = 2 // Implicitly Unwrapped Optional var c: Int = a! + 10 // Force Unwrap self?.collectionView?.reloadData() // Optional Chaining
  18. 28.

    参考文献 1. 詳解 Swift 改訂版 2016 年 1 月 1

    日 初版第一刷発行 http://amzn.asia/eeKqCsH Swift3 系はこちら:http://amzn.asia/4IXtxem 2. どこよりも分かりやすい Swift の "?" と "!" http://qiita.com/maiki055/items/b24378a3707bd35a31a8