2014年8月22日金曜日

swiftのnullの扱い

WWDCで発表された新言語swift。
実際使ってアプリ作らないと分からない ということで、使い始めています。

ObjectiveCを使い始めた時に戸惑ったことの一つとして、
nullのものに対して処理を書いてもプログラムが落ちないということ。
また、違うクラス型にcastしてもプログラムが落ちないということ。
ここの部分、プログラムを落とすことができるようになっています。

変数の記述には、

(1) var name:String
(2) var name:String?
(3) var name:String!

の書き方があります。

(1) は、null は絶対設定されないのを保証する形式。
定数宣言時に var name:String = "abc"
と値を入れるか、初期化時(init)で値を入れる記述がないと、コンパイルエラーになります。もちろん、後でnull入れようとしてもコンパイルエラー。

(2)は、nullも入る可能性があるもの。
この場合、このオブジェクトに操作をするときは

name?.uppercaseString
のように ? をつける必要があります。
nameがnullだったとしても落ちません。

(3)は、初期化時はnullだけど、後でnull以外の何かが入る という時の形式。
たとえば、Storyboardで記述したUIオブジェクトをつなげているものとか。
この形式だと、
name.uppercaseString
..と?ナシで記述ができますが、もしnameがnullだったら落ちます。
nullを入れることもできます。

? で宣言している変数を、
name!.uppercaseString
と、!にすることも可能です。(Unwrap)

明確に、nullの可能性がある、無い というのがわかるので、
SDKも含め、他人のコードを呼び出すときにはとっても助かります。
(SDKのメソッドの引数は!が多い...)

自分のコードでも、
なぜ動かない? となった時、実はnullだった ということもよくあった。
違うクラス型にcastしてしまった時も、それに気づくのはcast時でなくてそのオブジェクトの変数やメソッドにアクセスした時にエラーで気づくので、どのタイミングでcast間違えた?と戻って考えないといけないこともあった。

なので、嬉しい反面、nullについては、ちょっと面倒だな と思うことも。

たとえば、UIは後回しでコードをざざっと書いてしまおう! という時。
「この変数は後でStoryboardからUI部品つなげるから、今はnullだけど、あとで繋ぐからいまはOK〜」 という感じでバーっと書くことがよくあった。

こんなとき、? で書けばよいのだろうけど、UIができた最終形では ! で書きたい。
開発途中の今は nullで落ちてほしくなけど、リリース時の最終形ではnullで落ちて欲しいという欲張りな要望です....

? で宣言すると、メソッドやプロパティアクセスする度に、?の記述が入るので、それらを後で削除するのが面倒。
! で宣言すると、開発途中だと落ちちゃうのでnullチェックのif文を入れる...としても、if文を後で削除するのも面倒。

開発途中だから暫定に入れたコードというのは消すのを忘れがちで、残ってしまうのはとっても嫌。バグの元になるし、後でコード見た時も混乱の元。
? や !は、最初から想定している指定で書くのがやっぱりいいと思う。
ということで、今、UIできていないところは、ガンガン落ちるプログラムで開発中です(笑)


• • •