もくじ
初めまして、iOSをメインに開発しているロッキーカナイです。
これまでObjective-CでiOS開発をしていたのですが、Swiftを扱うことになり、いきなりズッコケたのがこのオプショナルという、!や?のやつです。今回はSwiftを扱うなら必ず覚えなければならないオプショナルをまとめてみました。
非オプショナル型とオプショナル型
非オプショナル型
変数にnilの代入を許容しないデータ型が非オプショナル型
例
var num: Int = 100
var text: String = “ABC”
nilを許容しない為、変数宣言と同時にデータの代入をする必要があります。
オプショナル型
変数にnilの代入を許容するデータ型がオプショナル型
例
パターン1 var num: Int? = 100
パターン2 var num2: Int?
パターン3 var num3: Int? = nil
パターン1 var text: String! = “ABC”
パターン2 var text2: String!
パターン3 var text3: String! = nil
nilを許容する為、変数宣言にデータの代入をする必要はありません。
パターン1では変数宣言と同時に代入するパターン。
パターン2は変数宣言のみを行うパターン(この場合にはnilが初期値となります)
パターン3は変数宣言とnil代入を行っているパターン(パターン2と同等)
ここまでのポイント
変数宣言時の型になにもつかないと非オプショナル型で、型に!や?がつくとオプショナル型
?と!の違いとは
?(Optional Value)
一般的にオプショナル型というと?を指し、簡単に言ってしまうと手動でアンラップする必要があるものです。アンラップとはオプショナル型同士やオプショナル型と非オプショナルでは計算や比較が出来ないのでオプショナル型からデータを取り出すことを言います。
例
var num: Int? = 100
let sum: Int = 10
let total: Int = sum + num!
num!とすることでアンラップし計算が可能になる(アンラップについては別途まとめてます)
!(Implicitly Unwrapped Optional)
暗黙的アンラップ型といい、計算や代入などで使用する際に暗黙的にアンラップするオプショナル型になります。
例
var num: Int! = 100
let sum: Int = 10
let total: Int = sum + num
暗黙的アンラップで宣言されたオプショナル型は計算時に暗黙的にアンラップします
ここまでのポイント
オプショナル型にするには型に?や!をつける。
使用?は手動でアンラップしてあげる必要があり、!は暗黙的にアンラップしてくれる。
アンラップの種類
アンラップの方法もいくつかあります。
オプショナルバインディング(Optional Binding)
オプショナルチェイニング(Optional Chaining)
強制的アンラップ(Forced Unwrapping)
アンラップ時に便利な??演算子
オプショナルバインディング(Optional Binding)
オプショナルチェイニングはアンラップを伴わずに安全にラップされた型のプロパティやメソッドにアクセスする記法になります。
オプショナル型の変数に値が入っている場合、変数をアンラップし、中身を取り出します。
例
val num: Int? = nil
if let unwrappedNum = num {
// numがnilでない場合変数unwrappedNumにはInt型の数値が入ります
print(unwrappedNum)
} else {
print(“Int?型のnumはnilです”)
}
※numはnilなのでelseに入ります
オプショナルチェイニング(Optional Chaining)
オプショナルチェイニングは、オプショナル型の変数の中身がnilの時に安全にプログラムを実行するための記法です。オプショナルチェイニングはオプショナル型の変数のあとに”?”をつけ使用します。
例
オプショナル型変数?.メソッド()
オプショナル型変数?.プロパティ
オプショナル型変数がnilの場合は?以降に記述されたプロパティやメソッドのアクセスは実行されずnilが返ります。また、nilでない場合の返却される型はオプショナル型になります。
例
let name: String? = “name”
let lowercased = name?.lowercased()
定数lowercasedにはString?が返却されるので、もし定数に型指定をする場合は、let lowercased: String?と記述しないといけません。(ちなみにString型のlowercased()の戻り型はStringです。name?で記述した場合の戻り型はすべてオプショナル型になるので注意してください)
強制的アンラップ(Forced Unwrapping)
強制的アンラップはオプショナル型を強制的にアンラップし値を取得する記法です。ただし、オプショナル型の変数がnilだった場合は、アプリがクラッシュするので、必ずnilでない場合に記述する必要があります。
例
let sum: Int? = 10
let total: Int = 10 + num!
オプショナル型の変数の後に!をつけることで強制的アンラップし、値を取り出します。
プロパティやメソッドのアクセス時にも使用可能です
let name: String? = “name”
let lowercased: String = name!.lowercased()
オプショナルチェイニング時の?とは違い、!で返却される型はオプショナル型ではなくアンラップさらた型になります。
??演算子
オプショナル型に値が存在しない場合のデフォルト値を指定する記法です。
例
val lastName: String? = nil
let name: String = lastName ?? “kanai”
lastNameがnilの場合にデフォルト値として”kanai”が代入されます。
ここまでのポイント
オプショナルバインディング(Optional Binding)は、if letを使用し安全にアンラップする記法
オプショナルチェイニング(Optional Chaining)は、?を使用し安全にアクセスする記法
強制的アンラップ(Forced Unwrapping)は、!を使用し強制的にアンラップする記法で、nilの場合はアプリがクラッシュする為、nilでない場合に使用する
どうでしたでしょうか?なんとなくオプショナル型について全体像が見えてきたのではないでしょうか?
Objective-Cではポインタを使用したデータはすべてnilが代入できたのに対しSwiftではオプショナル型でないとnilが代入できないので、nilに厳格になった点が大きく異なります。
これはプログラマが意図しないnilアクセスでアプリがクラッシュしてしまうのを防ぐことにつながっており、オプショナル型を使いこなすことで、よりクラッシュが少なく、より安全に、効率よくコーディングできるものだと考えております。
今回オプショナルの説明しましたが、ご覧頂けた方に少しでも理解頂けたらな幸いです。今後もマイペースにSwiftの記事を載せて行きたいと思います。
環境 Swift4 Xcode9