SwiftでResultとthrowsを使い分ける目安

Swiftで失敗する処理を書くとき、throws にするか Result にするか迷うことがあります。

呼び出してすぐ処理するなら throws、結果を値として保持したいなら Result、くらいで見ると整理しやすいです。

throwsを使う場面

enum LoadError: Error {
    case notFound
}

func loadName() throws -> String {
    throw LoadError.notFound
}

呼び出し側では do-catch で扱います。

do {
    let name = try loadName()
    print(name)
} catch {
    print(error)
}

普通の関数呼び出しとして書けるので、失敗をその場で処理するなら throws が読みやすいです。

Swiftのエラーハンドリングは公式のLanguage Guideにもまとまっています。

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling/

Resultを使う場面

Result は成功か失敗かを値として持てます。

let result: Result<String, Error> = .success("Makonote")

状態として保持したい場合に向いています。

enum ViewState {
    case idle
    case loaded(Result<String, Error>)
}

非同期処理の完了結果を一度プロパティに保持したい場合などは、Result の方が扱いやすいことがあります。

async throws

非同期処理なら async throws にできます。

func fetchName() async throws -> String {
    "Makonote"
}

呼び出し側では try await します。

let name = try await fetchName()

async/await の基本は Swiftでasync/awaitとTaskを使うときに最初に見ること に分けています。

まとめ

throwsResult は、失敗をどう扱いたいかで分けます。

  • その場で呼び出して処理するなら throws
  • 非同期なら async throws
  • 結果を状態として保持するなら Result
  • UI状態に持つなら Result が合うこともある

まずは throws で書き、値として持ち回りたくなったら Result を考える流れで十分です。

関連記事

参考