SwiftUIの基本を身につけたい方はこちら

【Swift】オプショナル型(Optional)について徹底解説~アンラップについても解説「!」「?」「??」、guard let、if let~

この記事では、初心者の方に向けてオプショナル型はなんなのかを解説していきたいと思います。

おそらく今この記事を見てる方は、いろいろなオプショナル型の記事を見てもなんとなくしか理解できていない状態だと思います。自分もそうでした。

この記事では、過去の自分に向けて解説するつもりで書いていきたいと思います。

オプショナル型とは?

オプショナル型というのは、値の中身が空(nil)の可能性がある値をのことを言います。

Xcodeで開発していれば誰もが経験あると思いますが、値に対してのエラーからまるぽち押して「Fix」を押したときに、!??がつく値のことです。

Textの中に値を入れたりするときに、nilの値が入るとエラーになります。

なので、nilかどうかわからないオプショナル型を入れるときは、必ずnilでないことを保証したり、nilだった場合は行わない。みたいな感じでnilを代入しないようにしなければなりません。

オプショナル型のアンラップとは?

オプショナル型は、nilの可能性がある型のことです。では、上記のスクショのvar str: String?は、何型かというと、String型であり、オプショナル型です。String型をオプショナル型で包んでいるラップしているという形です。

オプショナル型で包まれている変数は、nilの可能性があるので、そのままTextや代入に使用するとエラーが発生してしまいます。

そこで、使用する前に、その変数をオプショナル型を剥がさないといけません。この剥がすことを、アンラップと言います。

アンラップの手段としては、その変数に対して!や、??をつけてnilでないことを保証したり、nilだった場合は処理を行わないようにすることのことを言います。

なので、上記のFixの対応は、オプショナルのアンラップを自動的に行なってくれているということになります。

アンラップの方法は、主に以下の4パターンあります。それぞれ解説していきたいと思います。

  1. 「!」強制アンラップ
  2. 「??」??演算子(nil合体演算子)のアンラップ
  3. if letを使ったアンラップ
  4. guard let を使ったアンラップ

「!」強制アンラップ

値の後ろに!をつけるアンラップ方法です。これが一番簡単な方法ですが、欠点があります。

それは、もしその値がnilだった場合、プログラムが止まりエラーになります。プログラムが止まるというのは、アプリをリリースしている場合だとクラッシュになりますので、非常に危険です。

そのため、この強制アンラップというのはなるべく使わないようにしなければなりません。

struct ContentView: View {
    var str: String? = "こんにちは"
    
    var body: some View {
        Text(textStr())
            .padding()
    }
    
    func textStr() -> String {
        return str!
    }
}

「??」??演算子(nil合体演算子)のアンラップ

値の後ろに?? 代用の値をつけるアンラップ方法です。

もしその値がnilだった場合、代用の値を使うというイメージです。なので、以下のコードは、もしstrnilだった場合、"代用"という文字列が表示されます。上記の強制アンラップを使うよりなら、こちらの方を使った方が安全です。

struct ContentView: View {
    var str: String? = "こんにちは"
    
    var body: some View {
        Text(textStr())
            .padding()
    }
    
    func textStr() -> String {
        return str ?? "代用"
    }
}

if letを使ったアンラップ

以下のプログラムは、strsに代入してみてsnilじゃなかったら、Textsを表示します。もしsnilだったらif文内の処理は行いません。つまりTextが表示されません。

このif let文は、strsに代入してみて、nilじゃない場合に中の処理を実行するというアンラップ方法です。

nilじゃなかった場合は、そもそも処理を実行しないので、上記の??演算子よりも親切で安全なコードになります。

struct ContentView: View {
    var str: String? = "こんにちは"
    
    var body: some View {
        if let s = str {
            Text(s)
                .padding()
        }
    }
}

guard let を使ったアンラップ

guard letは、そのまま「ガード」という意味で、もしsstrを代入してみてnilだったらそれ以下の処理は行わないというアンラップ方法です。その後ろのコードは行わないのでまさにガードしています。

なので、以下のプログラムの場合は、strnilだった場合は、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という変数にint1を足して代入しています。しかし、このオプショナルをアンラップしていないため、エラーになります。

var int: Int?
var i = int + 1 // アンラップしていないためエラー

エラーを解消するには、以下のようにアンラップしなければなりません。なのでアンラップします。intnilだった場合は代用として0を使うようにします。

var int: Int?
var i = int ?? 0 + 1

これでビルドが通って実行すると、i1になります。

ちなみに、!を使ったアンラップだと、使う時にnilだった場合エラーになるので、ビルドは通りますが、実行するとエラーになります。←ここ何言っているかわからない方は、上記の「!」を使ったアンラップを読み直してください。

var int: Int?
var i = int! + 1 // 実行するとエラー

「型!」のオプショナル型について

では、次に型の後ろに!をつけるオプショナル型について解説します。

以下のコードは、上記と同じくintというオプショナル型を宣言して、iという変数にint1を足して代入しています。「型?」の場合はここでエラーになりますが、「型!」はエラーになりません。

なぜかというと、「!」を使ったアンラップと同じようにこの値が、もしnilだった場合、エラーになるという宣言だからです。ビルドは通りますが、実行してみるとエラーになるはずです。

var int: Int!
var i = int + 1 // 実行するとエラー

じゃあどうすればエラーにならなくなるのかというと、普通にnilじゃない形にすれば良いだけです。

var int: Int!
int = 20
var i = int + 1

おまけ

?? ""を毎回書くのめんどくさいというか、カッコ悪いのでこのExtensionを使ってます。

まとめ

ここまでオプショナル型について解説してきました。理解できましたでしょうか?

正直、Swift初心者には理解が難しいと思います。自分も最初全然理解できてませんでしたし。。。でも色々と開発していくうちになんとなくわかっていきます。1年くらい開発していれば流石に染み付いて、なんでこんなのもわからなかったんだろうっていうふうになると思うので諦めずに開発を続けてください。

もし、しっかりと理解したいというのであれば、MENTAというサービスで、ビデオ通話やチャットにてiOSアプリ開発を教えているので、興味があったらみてみてください。

まずは相談からでもOKです!

MENTAのプランを見てみる

評価