オプショナルバインディング
型の存在の有無を冗長な書き方にしないためのif-let構文。if letで指定したOptional型の変数がnilでなければ、構文の中でアンラップ済みの変数を使えるようにする。
ダウンキャストもif letで対応できる。
let oa = Optional("a")
if let a = oa {
print("\(a)")
} else {
print("nil")
}
let ob = Optional("b")
if let a = oa, let b = ob {
print("\(a),\(b)")
} else {
print("nil")
}
let any : Any = 1
if let iany = any as? Int {
print("\(iany)")
}
guard,guard-let
ある関数のスコープ内で、guardで指定した条件が満たされることを保証する。
関数の先頭で引数に対してguardを定義することで引数の前提条件を書いたりする。
if-letのguard版(guard-let)もある。
func someFunc() {
let value = 1
guard value >= 0 else {
return
}
// ここまで来たならvalueが0以上であることを保証する
print("0以上です。")
}
func someFunc2() {
let any : Any = 1
guard let iany = any as? Int else {
return
}
print("\(iany)")
}
nil可能な引数を取る加算関数をif,guard両方で書くと以下。
guardで書いた方が見通しがよくなる。
func add(_optionalA:Int?, _optionalB:Int?) -> Int? {
let a: Int
let b: Int
if let unwrappedA = _optionalA {
a = unwrappedA
} else {
return nil
}
if let unwrappedB = _optionalB {
b = unwrappedB
} else {
return nil
}
return a + b
}
func add2(_optionalA:Int?, _optionalB:Int?) -> Int? {
guard let a = _optionalA else {
return nil
}
guard let b = _optionalB else {
return nil
}
return a + b
}
for-in,for-case
for-inで要素の全てにアクセスする。for-caseで条件を満たす要素にアクセスする。
foreachで回す先頭で条件でスキップする奴はfor-caseで書ける。
let dict:Dictionary = ["a":1,"b":2]
for (key,value) in dict {
print("\(key):\(value)")
}
let ary:Array = [1,2,3,4]
for case 2...3 in ary {
print("2以上3以下")
}
fallthrough
switch文の各caseの終わりでfallthroughを書いたときに初めて後ろのcaseが実行される。
fallthroughを書かないと条件にマッチしたcaseした実行されない。
なので、switch-caseの各caseの末尾にbreakを書く必要はない。
let a = 1
switch a {
case 1:
print("case1")
fallthrough
case 2:
print("case2")
default:
print("other")
}
遅延実行
関数の評価時ではなく、関数のスコープから抜けたときに実行する文を記述する。
以下、関数評価時にはgは0だが、関数がスコープから抜けたときにdeferが評価されgが1になる。
var g = 0
func someFunc2() -> Int {
defer {
g += 1
}
print("\(g)")
return g
}
someFunc2()
print("\(g)")