この記事では、初心者の方に向けてオプショナル型はなんなのかを解説していきたいと思います。
おそらく今この記事を見てる方は、いろいろなオプショナル型の記事を見てもなんとなくしか理解できていない状態だと思います。自分もそうでした。
この記事では、過去の自分に向けて解説するつもりで書いていきたいと思います。
Contents
オプショナル型とは?
オプショナル型というのは、値の中身が空(nil
)の可能性がある値をのことを言います。
Xcodeで開発していれば誰もが経験あると思いますが、値に対してのエラーからまるぽち押して「Fix」を押したときに、!
か??
がつく値のことです。
Textの中に値を入れたりするときに、nil
の値が入るとエラーになります。
なので、nil
かどうかわからないオプショナル型を入れるときは、必ずnil
でないことを保証したり、nil
だった場合は行わない。みたいな感じでnil
を代入しないようにしなければなりません。
オプショナル型のアンラップとは?
オプショナル型は、nil
の可能性がある型のことです。では、上記のスクショのvar str: String?
は、何型かというと、String型であり、オプショナル型です。String型をオプショナル型で
オプショナル型で包まれている変数は、nilの可能性があるので、そのままTextや代入に使用するとエラーが発生してしまいます。
そこで、使用する前に、その変数をオプショナル型を剥がさないといけません。この剥がすことを、アンラップと言います。
アンラップの手段としては、その変数に対して!
や、??
をつけてnil
でないことを保証したり、nil
だった場合は処理を行わないようにすることのことを言います。
なので、上記のFixの対応は、オプショナルのアンラップを自動的に行なってくれているということになります。
アンラップの方法は、主に以下の4パターンあります。それぞれ解説していきたいと思います。
- 「!」強制アンラップ
- 「??」??演算子(nil合体演算子)のアンラップ
- if letを使ったアンラップ
- guard let を使ったアンラップ
「!」強制アンラップ
値の後ろに!
をつけるアンラップ方法です。これが一番簡単な方法ですが、欠点があります。
それは、もしその値がnilだった場合、プログラムが止まりエラーになります。プログラムが止まるというのは、アプリをリリースしている場合だとクラッシュになりますので、非常に危険です。
そのため、この強制アンラップというのはなるべく使わないようにしなければなりません。
struct ContentView: View { var str: String? = "こんにちは" var body: some View { Text(textStr()) .padding() } func textStr() -> String { return str! } }
「??」??演算子(nil合体演算子)のアンラップ
値の後ろに?? 代用の値
をつけるアンラップ方法です。
もしその値がnil
だった場合、代用の値を使うというイメージです。なので、以下のコードは、もしstr
がnil
だった場合、"代用"
という文字列が表示されます。上記の強制アンラップを使うよりなら、こちらの方を使った方が安全です。
struct ContentView: View { var str: String? = "こんにちは" var body: some View { Text(textStr()) .padding() } func textStr() -> String { return str ?? "代用" } }
if letを使ったアンラップ
以下のプログラムは、str
をs
に代入してみてs
がnil
じゃなかったら、Text
でs
を表示します。もしs
がnil
だったらif文内の処理は行いません。つまりText
が表示されません。
このif let文は、str
をs
に代入してみて、nilじゃない場合に中の処理を実行するというアンラップ方法です。
nil
じゃなかった場合は、そもそも処理を実行しないので、上記の??演算子よりも親切で安全なコードになります。
struct ContentView: View { var str: String? = "こんにちは" var body: some View { if let s = str { Text(s) .padding() } } }
guard let を使ったアンラップ
guard let
は、そのまま「ガード」という意味で、もしs
にstr
を代入してみてnil
だったらそれ以下の処理は行わないというアンラップ方法です。その後ろのコードは行わないのでまさにガードしています。
なので、以下のプログラムの場合は、str
がnil
だった場合は、return s
が実行されずに、""
が返されます。もしnil
じゃなかったら、return s
が実行されてs
(こんにちは)が返されます。
struct ContentView: View { var str: String? = "こんにちは" var body: some View { Text(textStr()) .padding() } func textStr() -> String { guard let s = str else { return "" } return s } }
アンラップまとめ
アンラップは、上記のように4パターンありますが、状況に応じて使い分けなければなりません。
- 「!」強制アンラップは、危険だけど手っ取り早いので、試しに開発してみるときなどで使います。アプリの実装ではなるべく強制アンラップは使わないようにしています。
- 「??」??演算子のアンラップは、代用を用意してあげるだけなので簡単です。ただ、ちょっと特殊な型だとめんどくさいです。
if let
を使ったアンラップは、nilだった場合、そもそもその処理を行わないようにする対応ができるので、一番安全で良い対応だと思います。guard let
を使ったアンラップは、一番スマートですが、nil
だった時それ以降の処理を行わないので使う場面をしっかりと考えないといけません。
自分はこのように使い分けています。
オプショナルについてもう少し詳しく解説
上記では、オプショナル型についてざっと解説しましたが、これだけではなんとなくしかわからないと思うのでしっかりと解説していきたいと思います。
オプショナル型の宣言について
オプショナル型の宣言
オプショナル型の宣言は以下のように行います。全てオプショナル型の変数です。
var str: String? var int: Int? var str1: String? = "あああ" var int1: Int? = 10 var str2: String! var int2: Int! var str3: String! = "あああ" var int3: Int! = 10 // 使用頻度は少ないですが、以下のような書き方もできます。 var str4: Optional<String> = nil var int4: Optional<Int> = nil
非オプショナル型の宣言
逆に、オプショナル型ではない宣言は以下のように行います。全て非オプショナル型の変数です。
var str: String var int: Int var str1: String = "あああ" var int1: Int = 10
「型?」と「型!」の違いについて
違いは、エラーになるタイミングが違います。
「型?」のオプショナル型について
まずは型の後ろに?をつけるオプショナル型について解説します。
以下のコードは、int
というオプショナル型を宣言して、i
という変数にint
に1
を足して代入しています。しかし、このオプショナルをアンラップしていないため、エラーになります。
var int: Int? var i = int + 1 // アンラップしていないためエラー
エラーを解消するには、以下のようにアンラップしなければなりません。なのでアンラップします。int
がnil
だった場合は代用として0
を使うようにします。
var int: Int? var i = int ?? 0 + 1
これでビルドが通って実行すると、i
が1
になります。
ちなみに、!
を使ったアンラップだと、使う時にnil
だった場合エラーになるので、ビルドは通りますが、実行するとエラーになります。←ここ何言っているかわからない方は、上記の「!」を使ったアンラップを読み直してください。
var int: Int? var i = int! + 1 // 実行するとエラー
「型!」のオプショナル型について
では、次に型の後ろに!をつけるオプショナル型について解説します。
以下のコードは、上記と同じくint
というオプショナル型を宣言して、i
という変数にint
に1
を足して代入しています。「型?」の場合はここでエラーになりますが、「型!」はエラーになりません。
なぜかというと、「!」を使ったアンラップと同じようにこの値が、もしnilだった場合、エラーになるという宣言だからです。ビルドは通りますが、実行してみるとエラーになるはずです。
var int: Int! var i = int + 1 // 実行するとエラー
じゃあどうすればエラーにならなくなるのかというと、普通にnilじゃない形にすれば良いだけです。
var int: Int! int = 20 var i = int + 1
おまけ
?? ""
を毎回書くのめんどくさいというか、カッコ悪いのでこのExtensionを使ってます。
このリファクタリングはテンション上がった笑 pic.twitter.com/ahb28uo8af
— サトリク (@satorikublog) January 5, 2023
まとめ
ここまでオプショナル型について解説してきました。理解できましたでしょうか?
正直、Swift初心者には理解が難しいと思います。自分も最初全然理解できてませんでしたし。。。でも色々と開発していくうちになんとなくわかっていきます。1年くらい開発していれば流石に染み付いて、なんでこんなのもわからなかったんだろうっていうふうになると思うので諦めずに開発を続けてください。
もし、しっかりと理解したいというのであれば、MENTAというサービスで、ビデオ通話やチャットにてiOSアプリ開発を教えているので、興味があったらみてみてください。
まずは相談からでもOKです!