Just a Memo

_φ(・_・

オプショナル型を学んでみる

Swiftでは変数の値が無い時に使えるオプショナル型というものがあります

使い方としては、値が無い場合はnilを、値が定まったら実際の値を変数に代入します

オプショナル型の変数の値を使いたい場合は if文で変数がnilとチェックするか、
オプショナルバインディングを使うことでオプショナル型をunwrapすることができます



例としてnameとphoneNumberを持つPerson構造を見てみます

struct Person {
    var name: String
    var phoneNumber: String? // nilかStringの値を持つことができるオプショナルString型
}


スマホを持ってるAliceと持ってないBobをインスタンス化する際に、
Aliceは実際の番号を、Bobは値が無いのでnilをいれてあげます

var Alice = Person(name: "Alice", phoneNumber: "xxx-xxxx-1234")
var Bob = Person(name: "Bob", phoneNumber: nil)


値を保持→nilnil→値が保持、の変更も可能です

// アリスが携帯を解約 => 電話番号をnilにセットできる
Alice.phoneNumber = nil

// ボブが携帯を契約 => 電話番号をStringにセットできる
Bob.phoneNumber = "xxx-xxxx-5678"


オプショナル型をPrintしてみると、包装(wrap)がついてることがわかります

f:id:sanoa90:20180716061506p:plain


つまり値を使う際には値をunwrapしてあげる必要があります
unwrapは強制(!)かオプショナルバインディング(if let = ... {} ) の二通り

// !を使うと強制的にunwrapできる
if Bob.phoneNumber != nil {
    print(Bob.phoneNumber!) // => "xxx-xxxx-5678"
}


強制(!)unwrapはもし値が無い場合はエラーとなるため、
値が絶対入ってるとわかってる場合のみ単独で使い、
わからない場合は↑のようにnilと比較してからunwrapします

// 値の入ってない変数(要するにnil)をunwrapするとエラー
let optionalInt : Int? = nil
print(optionalInt!)  // => error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)


nilのチェックが面倒な人はオプショナルバインディングを使います
↓の if let A = B の形がオプショナルバインディングで、
BからAへのunwrapが成功した場合のみif文内部が実行されます

let optionalInt : Int? = 10
if let unwrappedInt = optionalInt { // optionalIntに値が入ってる場合のみif文内部を実行
    print(unwrappedInt) // => 10
}