Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Swift辞典

  1. トップページ
  2. Swift辞典
  3. Optional Chaining / map / flatMap(Optional)

Optional Chaining / map / flatMap(Optional)

Swiftの『Optional Chaining』(『?.』)は、Optionalがnilの場合に処理をスキップし、安全にプロパティやメソッドにアクセスする構文です。

構文
// Optional Chaining
optional?.property
optional?.method()

// チェーン(途中でnilならnil全体がnil)
optional?.propertyA?.propertyB

// Optional の map / flatMap
optional.map { $0 + 1 }        // nilならnil、値なら変換
optional.flatMap { Int($0) }   // nilまたは変換失敗でnil
構文一覧
構文概要
opt?.propertyoptがnilでなければpropertyにアクセスし、nilならnilを返します。
opt?.method()optがnilでなければメソッドを呼び出します。結果はOptionalになります。
opt?.a?.b?.c複数のOptionalをチェーンします。途中でnilになると全体がnilになります。
opt.map { 変換 }nilならnilを、値があれば変換した値をOptionalで返します。
opt.flatMap { 変換 }nilならnil、変換結果もOptionalを返す場合にネストを防ぎます。
opt.compactMap { 変換 }配列のOptional要素をアンラップし、nilを除外した配列を返します。
サンプルコード
// Optional Chainingの基本
class Address {
    var city: String
    init(city: String) { self.city = city }
}

class Person {
    var name: String
    var address: Address?
    init(name: String, address: Address? = nil) {
        self.name = name
        self.address = address
    }
}

let taro = Person(name: "太郎", address: Address(city: "東京"))
let hanako = Person(name: "花子")  // addressなし

// Optional Chainingでアクセス(nillでも安全)
print(taro.address?.city ?? "住所不明")    // 東京
print(hanako.address?.city ?? "住所不明")  // 住所不明

// Optional の map
let optNumber: Int? = 5
let doubled = optNumber.map { $0 * 2 }  // Optional(10)
let nilNumber: Int? = nil
let nilDoubled = nilNumber.map { $0 * 2 }  // nil

print(doubled ?? 0)    // 10
print(nilDoubled ?? 0) // 0

// flatMap(ネストしたOptionalを防ぐ)
let strNumber: String? = "42"
let parsed = strNumber.flatMap { Int($0) }  // Optional(42)
let invalid: String? = "abc"
let failedParsed = invalid.flatMap { Int($0) }  // nil

print(parsed ?? -1)       // 42
print(failedParsed ?? -1) // -1

// 配列での compactMap
let strings = ["1", "two", "3", "four", "5"]
let integers = strings.compactMap { Int($0) }
print(integers)  // [1, 3, 5]
概要

Optional Chaining(『?.』)を使うとOptionalが複数連なる複雑なオブジェクト構造でも安全にアクセスできます。チェーンの途中でnilがあると、その後の評価がスキップされ全体がnilになります。

『map』はOptionalの中身を変換し、結果もOptionalになります。『flatMap』は変換関数自体がOptionalを返す場合に使い、ネストした『Optional<Optional<T>>』を防ぎます。Optional Chainingの結果は常にOptionalになるため、使用時はアンラップが必要です。

Optionalの基本についてはOptional / ? / !を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。