言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Swift辞典

  1. トップページ
  2. Swift辞典
  3. Result<Success, Failure>

Result<Success, Failure>

対応: Swift 5.0(2019)

Swiftの『Result』型は、成功(.success)または失敗(.failure)のどちらかを表す enum です。非同期処理や関数の戻り値でエラーを値として扱う場合に使います。

構文

// Result 型の定義
// Result<Success, Failure>(Failure は Error プロトコルに準拠)
let result: Result<String, Error> = .success("データ")
let error:  Result<String, Error> = .failure(SomeError.failed)

// switch でパターンマッチ
switch result {
case .success(let value):
    print("成功: \(value)")
case .failure(let error):
    print("失敗: \(error)")
}

// get() で throws に変換
let value = try result.get()

メソッド一覧

メソッド概要
get()成功値を返します。失敗の場合はエラーを throw します。
map(_:)成功値を変換して新しい Result を返します。
mapError(_:)失敗のエラーを変換して新しい Result を返します。
flatMap(_:)成功値を使って別の Result を返すクロージャを適用します。
flatMapError(_:)失敗のエラーを使って別の Result を返すクロージャを適用します。

サンプルコード

『Result』型を使った成功・失敗の処理を確認するサンプルコードです。

sample_result_type.swift
enum AppError: Error {
    case notFound
    case parseError(String)
}

// Result を返す関数
func fetchUser(id: Int) -> Result<String, AppError> {
    let users = [1: "user_1", 2: "user_2", 3: "user_3"]
    if let user = users[id] {
        return .success(user)
    } else {
        return .failure(.notFound)
    }
}

// switch でパターンマッチ
let result = fetchUser(id: 2)
switch result {
case .success(let name):
    print("ユーザー: \(name)")
case .failure(let error):
    print("エラー: \(error)")
}

// map: 成功値を変換
let upperResult = result.map { $0.uppercased() }
print("大文字: \(try! upperResult.get())")

// flatMap: 成功値で別の Result を作成
func fetchDetail(name: String) -> Result<String, AppError> {
    return .success("\(name)のプロフィール")
}

let detail = result.flatMap { fetchDetail(name: $0) }
print(try! detail.get())

// get() で throws に変換
do {
    let name = try fetchUser(id: 99).get()
    print(name)
} catch AppError.notFound {
    print("ユーザーが見つかりません")
} catch {
    print("エラー: \(error)")
}

// コールバック系API との組み合わせ
func loadData(completion: (Result<[String], Error>) -> Void) {
    completion(.success(["item1", "item2", "item3"]))
}

loadData { result in
    switch result {
    case .success(let items): print("取得: \(items)")
    case .failure(let error): print("失敗: \(error)")
    }
}
swift result_type.swift
ユーザー: user_2
大文字: USER_2
user_2のプロフィール
ユーザーが見つかりません
取得: ["item1", "item2", "item3"]

概要

『Result』型はエラーを値として扱うため、非同期コールバックや関数の連鎖(chaining)に適しています。成功・失敗の両ケースを1つの戻り値で表現できます。

『map』『flatMap』を使うと、エラーチェックを省略しながら成功値を変換するパイプラインを構築できます。Swift Concurrency(async/await)が使える環境では、コールバックよりも async throws 関数を使う方が読みやすいコードになります。

エラーの定義についてはError / enum でエラー定義を参照してください。

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