dip Engineer Blog

Engineer Blog
ディップ株式会社のエンジニアによる技術ブログです。
弊社はバイトル・はたらこねっとなど様々なサービスを運営しています。

Swiftにおける「!」,「?」の意味とは

自己紹介

21新卒,スマートフォンアプリ開発課でiOSアプリ開発をしている城戸健汰です。 Swiftでの実務経験が無い中で学習をしていると、いろいろな壁にぶつかりました。その中で最も大きな壁だったのがこの!と?の概念や使い方でした。 今回学習したことのアウトプット・備忘録としてこの記事を書きます。

この記事を読んだあなたは、Swiftにおける!と?の使い方を大まかに理解できると思います!ぜひ最後まで読んでみてください。

Swiftの!と?の意味とは?

まず、Swiftの!と?には2つの使い方があります。

  • オプショナル型としての使い方
  • アンラップするための使い方

の2つです。順番に説明していきます。

オプショナル型としての使われ方

ここではオプショナル型の説明をしていきます。

オプショナル型とは?

結論から話すと、オプショナル型とは

変数にnilの代入を許すのがオプショナル型です Swiftにはオプショナル型と、非オプショナル型があります。 オプショナル型はnilの代入を許すもので、非オプショナル型はnilの代入を許さないものです。

なぜオプショナル型が必要なのか?

Swiftでは基本的にnilの値を参照しようとすると、他のnil(null)安全な言語と同様にアプリケーションが落ちてしまいます。ですが、オプショナル型を使うとnilの代入を許可するのでアプリが落ちることがなくなります。

ですが、全てにオプショナルを使ってしまうと、これから説明するアンラップという作業をする工程が増えるので、「絶対に値が入っているであろうもの」にはオプショナル型を適応しなくても大丈夫です。また、初期値が定義されているものもオプショナル型を使う必要はないです。

例えば、

var count = 0

と定義されているものは、初期値が0と決まっているのでnilになることはありません。 ですが

var count:Int

などの初期値が決まっていなく、nilの可能性があるものに対してオプショナル型をつけるのが妥当かもしれません。 ですが、あえて付けずにnilの値を混入させないようにするという考え方もあるため、場面によって考えましょう。

どうやって使うの?

オプショナル型の使い方は関数を宣言する際の型の後ろに ? か ! をつけることでオプショナル型となります。 例えば上記の例であれば

var count:Int?

var name:String!

と宣言することでオプショナル型になります。

!と?の違いは?

ここで、? と ! はどう違うの? と思った人も多いかと思います。 その違いとは、

  • ? は、一般的なオプショナル型であり

  • ! は、暗黙的アンラップ型と呼ばれるオプショナル型です。

この!と?違いについては"アンラップ"について説明が必要なので後ほど詳しく説明していきます。

アンラップするための使われ方

オプショナル型は宣言した後にその関数を使う際に、"アンラップ"という作業が必要である場合が多いです。

アンラップとは?なぜそれが必要なの?

アンラップとはなんなのか、なぜそれが必要なのかを例を交えて簡単に説明していきます。 例えば、

var name:String
name = "kido"
print(name)

とした場合は ->

kido

と帰ってきます。ですがオプショナル型で宣言すると

var name:String?
name = "kido"
print(name)

とした場合は ->

Optional("kido")

と帰ってきます。 オプショナルで宣言したものをそのまま使用すると、 Optional("中身")と帰ってきてしまいます。これを外すことをアンラップと呼びます。

アンラップの方法は?

アンラップには!を使います。 下記の例にように宣言した関数の後ろに!をつけることでアンラップすることができます。

var name:String?
name = "kido"
print(name!)

とすると ->

 kido

と帰ってくるのでアンラップできたことになります。

アンラップの種類

アンラップには

  • 強制的アンラップ
  • オプショナルバインディング
  • オプショナルチェイニング

の3つの種類があります。

1つ1つ説明してきます。

強制的アンラップ

強制的アンラップは、先程の例で説明した 変数の後に「!」をつけてアンラップする方法です。

強制的アンラップには気をつけなければならない点が一つあり、 アンラップする対象のオプショナル型の関数の中身がnilだった場合、エラーでアプリケーションが落ちてしまう可能性があります。ですので強制的アンラップをする場合は必ず宣言した変数の中身が存在する(nilではない)ことが保証されていなければなりません。

オプショナルバインディング

オプショナルバインディングは、if文を使い条件分岐させ、nilでない場合、nilだった場合の処理を書くことを指します。 構文には、if let 、もしくはguard let を使います。

if letを使った場合の例文
var hobby: String?
 if let unwrappedHobby = hobby {  
​    print(unwrappedHobby)   
 } else {   
  print("趣味はありません")
}
guard letを使った場合の例文
var hobby: String?
 guard let unwrappedHobby = hobby else {  
​    print("nilです")   
 }
print(unwrappedHobby)

とできます。

ちなみに、guard letを使うと、guard let以降で宣言された変数や定数が利用可能かつ、if letは冗長なコードになりやすいため、guard letでオプショナルバインディングする方がおすすめです。

オプショナルチェイニング

オプショナルチェイニングはオプショナル型の変数の後ろに"?"をつけ、その後に続けてプロパティにアクセスしたりメソッドを呼び出す方法です。

例文

var human1: Human? = Human()
var human2: Human?
 human1?.name
 human2?.hello()

となります。

まとめ

Swiftにおける?と!の使い方は初期段階ではかなりつまづきやすいにもかかわらず、かなり多用されるものです。 xcodeのfixを使えば大体は補完をしてくれますが、理解して使わないと思わぬエラーの原因につながりかねませんのでこの機会にぜひ学習してみて欲しいです。