はじめに
こちらは前回の記事(Swiftの”?”と”!”,はじめからていねいに (1/2))の続きになります.今回もSwiftの”?”・”!”をまとめていきます.
前回のおさらい
前回の記事では最後にOptional Chainingの説明の際,以下の例を挙げました.
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
if john.residence?.numberOfRooms != nil {
let roomCount = john.residence?.numberOfRooms ?? 0
print(roomCount)
} else {
print("住所なし")
}
こちらの例では,Personクラスのオプショナル型プロパティresidenceがnilか否かによって,後続の処理をif文によって分岐させています.このように(一般的な)if文によってオプショナル型変数にまつわる処理の分岐を記述することができますが,SwiftではOpitional Bindingと呼ばれる仕組みによってこれらの分岐をより分かりやすく記述することができます.
表題の”?”・”!”は直接出てきませんが,オプショナル型の変数を扱うためには切り離せないものなので,まとめます.
Optional Binding (オプショナルバイディング)
前述の通り, Optional Binding(オプショナルバイディング)とはアンラップする変数にnilが入っている場合とそうでない場合で処理を分岐させる仕組みのことです.Optional Bindingには以下の2つの構文があります.
- if let
- guard let
if let
if let 文は以下のような構文で分岐させる処理を記述します.
if let <変数> = <オプショナル型変数> {
// <オプショナル型変数>にnilが含まれていない場合の処理
} else {
// <オプショナル型変数>にnilが含まれている場合の処理
}
if let 文では条件式右辺のにnilが含まれていない場合,アンラップした値をローカル変数である左辺のとして,ブロック内で使用することができます.
例
var fuga : Int? = 10//オプショナルInt型(nilを許容する)
if let _fuga = fuga {
print(_fuga)
} else {
print("にる")
}
//----出力----
//10
したがって,冒頭で再掲した前回のPerson型の例は以下のように記述することができます.
let john = Person()
john.residence = Residence()
if let _numberOfRooms = john.residence?.numberOfRooms {
print(_numberOfRooms)
} else {
print("住所なし")//こちらが出力される
}
let john = Person()
john.residence = Residence()//ここを追加
if let _numberOfRooms = john.residence?.numberOfRooms {
print(_numberOfRooms)//こちらが出力される(1)
} else {
print("住所なし")
}
guard let
guard let 文を用いることで,アンラップ時にオプショナル型変数にnilが含まれている場合,その時点で処理を中断させることができます.guard let 文は関数の中でのみ使うことができます.(この記事で使う例を検証してる時にめっちゃハマった)
guard let <変数> = <オプショナル型変数> else { return }
//後続処理
例
func printFuga(_ fuga: Int?) {
guard let _fuga = fuga else { return }
print(_fuga)
}
var fuga : Int? = 10//オプショナルInt型(nilを許容する)
printFuga(fuga)
//----出力----
//10
guard let 文では,if let 文と異なり,アンラップした値(_fuga)をguard let 文以降でも用いることができます.
式の中にある”?”と”??”
変数の型や変数名の後ろ以外にも,演算子として”?”が登場する場合があります.”?”・”??”でそれぞれ意味が異なります.
三項演算子 “?”
“?”が1文字の場合は三項演算子の意味を持ちます.構文は以下の通りです.
変数 = 条件式 ? (真の場合の値) : (偽の場合の値)
例
let a = 10
let b = 20
let result = a == b ? "EQUAL" : "NOT EQUAL"
print(result)//NOT EQUAL
三項演算子自体はオプショナル型と直接関係はありません.
Nil coalescing operator “??”
“??”が2文字の場合はNil coalescing operatorと呼ばれる演算子の意味を持ちます.
変数 = オプショナル型変数 ?? (値が格納されている場合の値) : (nilの場合の値)
三項演算子”?”が条件式の真偽によって評価の値を分岐させるのに対して,Nil coalescing operator “??” はオプショナル型変数がnilか否かで評価の値が分岐します.オプショナル型の変数がnilだった場合に代入するデフォルト値などを扱うのに便利です.
例
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
let _numberOfRooms = john.residence?.numberOfRooms ?? 0
print(_numberOfRooms.description)//0
asの後ろの”?”と”!”
最後にまとめる”?”・”!”はas演算子の後ろにつくものです.as?・as!演算子は型キャストのうちダウンキャストを行う際に用いるものです.
as?
ダウンキャストが失敗する可能性があり実際に失敗した場合,nilを返します.また,成功時にはオプショナル型を返します.
例
let any: Any = "abc"
let str = any as? String //Optional("abc")
let num = any as? Int //nil
as!
ダウンキャスト時に強制的に型キャストを行います.失敗した場合,その時点でエラーを出します.
let any: Any = "abc"
let str = any as! String //String型"abc"
let num = any as! Int //Int型にキャスト失敗(実行時エラー)
まとめ
今回の記事で扱った”?”・”!”のまとめです.

参考
河野穣
2019年新卒のエンジニアです.iOS修行中.