Swift: アウトレットを含めたプロパティで Optional “?” を積極的に使う

Swiftの特徴として、クラス名のみで示す型では、nil値を許さないことです。一方、?や!でnil値を許す変数の定義などができます。それぞれ、OptionalとUnwrapped Optionalと呼ばれています。

var myLabel1: UILabel = UILabel(frame: ...) // nilを許さないので何か入力しないといけない
var myLabel2: UILabel?
var myLabel3: UILabel!

ここで、アウトレットについて考えてみます。アウトレットは、Interface Builderで線を引くなどして参照先のオブジェクトが指定されていれば、ストーリーボードのロード時などに自動的に参照先が設定されます。しかしながら、オブジェクト生成直後では値が確定しないので、OptionalかUnwrapped Optionalのどちらかにしないといけません。

ここで、Appleのドキュメントでは、Unwrapped Optionalにすべきと書かれており、Xcodeでアシスタントエディタで、Interface Builderのオブジェクトからctrl+ドラッグでコード上にドロップしたときに作られるプロパティは、自動的にUnwrapped Optionalになります。もし、アウトレットをOptionalで定義すると、Optional Binding、つまり、

if let aLabel = myLabel2 {
    x = aLabel.text
}

のように、ifで囲う必要があります。そうなると、Objective-Cで作られたプログラムを移植するようなときに、流れが変わってしまい、作業効率が悪くなるということもあると思います。こうした点を総合して、AppleはUnwrap Optionalをアウトレットの推奨形態にしていると思われます。

しかしながら、Optionalか、Unwrap Optionalかは、仕組みの上ではどちらでも構わないのではないでしょうか。つまり、nil値を許せばいいのです。また、nil値になる状態での不要な処理を避けるという意味では、明示的にOptional Bindingを記述することになるので、不都合はなく、むしろ好都合かもしれません。余分に記述するのが目障りということもあるかもしれませんが、予防的な措置であれば、むしろ歓迎すべきです。これらの点は、個人的な嗜好ではありますが、むしろ評価すべきです。そもそも、Swfitは安全な言語ということが謳い文句だったはずです。であれば、Optionalをもっと積極的に使うべきではないでしょうか。

Optionalにしたら、面倒と思うかもしれません。たとえば、以下はいずれも、エラーになります。tagというプロパティはないとエラーでは記述されています。

myLabel2.tag = 3
let m = myLabel2.tag

しかしながら、若干の誤差を許していただければ、基本的には非常に緩いルールでこれらのエラーは逃れられます。それは、Optionalなプロパティが左辺にあるときには、単に、変数名に?をつけるだけでいいのです。右辺で利用するときには原則としてバインディングを行います。

myLabel2?.text = "aaa";
if let label = myLabel2 {
     let m = label.text
}

これだけのことでいいのです。これだけのことで、より安全になるのであれば、手間をかける価値はあるのではないでしょうか? アウトレットを含めたプロパティは、Optionalで定義する〜このルールでも構わないと考えます。