[Swift]プロジェクトのオプショナルバインディング対応


概要

 プロジェクトの保守として、強制アンラップされている箇所をオプショナルバインディングに変更していきたい。その際のチェックの仕方や、どの様に修正するかをまとめていく

修正したい箇所

1.hoge! のような強制アンラップ

オプショナル型の変数を非オプショナル型として使いたい時(特定のメソッドで引数として等)、強制アンラップをして使うと、もし値が取得できなかった場合にクラッシュしてしまうなどの危険がある。

2.= nillでのnillチェック

if 変数 = nillで早期returnさせても、その変数を使うときは強制アンラップしないとコンパイルできない。(動作としては問題ないが、強制アンラップしているかどうかが一目で分かりづらいので、メンテナンスのしやすさという観点から変更したい。基本的にはプロジェクトの方針に合わせる。)

その為、以下の様な対応でオプショナルバインディングをする。

guard-let構文

元のコード1.swift
method(hoge!.image)
元のコード2.swift
if hoge.image == nil { return }
let image = hoge!.image
method(image)
修正後.swift
guard let image = hoge.image else { return }
method(image)

このすると、hogeがnilでimageに値が入らない場合(imageにnilが入ってしまう場合)にはreturnによって処理を抜けることができる。

また、取得したい値がアンラップしたい変数そのものだった場合、わざわざスコープ内変数を設定せずに、_を用いてオプショナルバインディングだけする方法もある。

元のコード.swift
method(hoge!)
修正後.swift
guard let _ = hoge else { return }
method(hoge)
複数の変数を一気にオプショナルバインディング

どれか一つでも値を取得できなければ、処理を抜けたい!っていう時は、一括でオプショナルバインディングすることができる。

元のコード1.swift
method(a!, b!, c!)
元のコード2.swift
if a == nil || b == nil || c == nil { return }
method(a!, b!, c!)
修正後.swift
guard let a = a,
      let b = b,
      let c = c else { return }
method(a, b, c)

また、別の処理で使う変数であっても、同じスコープ内であれば、
スコープの最初に一括でオプショナルバインディングする方が無駄な処理をさせなくて済む。

元のコード.swift
guard let a = a else { return }
method1(a)

guard let b = b else { return }
method2(b)

guard let c = c else { return }
method3(c)
修正後.swift
guard let a = a,
      let b = b,
      let c = c else { return }

method1(a)
method2(b)
method3(c)

If-Let構文

値が取得できなかったら処理を抜けるというguard-let構文に対し、
値が取得できたら特定の処理を行うという書き方ができるのがIf-Let構文。

imageが取得できてもできなくても、method2()は走らせたい!っていう場合に、

guard-let.swift
guard let image = hoge.image else { return }
method1(hoge)

// imageが取得できなかった場合処理を抜けてしまうのでmethod2()は走らない
method2()
if-let.swift
if let image = hoge.image { method1(image) }

// imageが取得できなくてもmethod2()は走る
method2()

上記の様に、If-Let構文を使うことで、値が取得できなくても次の処理に行くことができる。

注意点

強制アンラップを避けることで、取得したい値が何らかの理由により取得できなかった場合、クラッシュさせずに処理を抜けることができる。

しかし、ユーザー側からすると「画面は正常なのに、操作しても反応しない! 」という状況になる場合もある。

その為、必要に応じて

  • 処理を抜ける際にアラートを表示させる処理を追加
  • 強制アンラップの結果、あえてクラッシュさせることで不具合が起きている状況を明らかにしたり、それ以上の操作ができない状態にする

などの対応をとることも考える。