[Swift][SwiftUI] Result 活用のすすめ

SwiftUI

Swift が標準的に用意している Result の使い方を改めて説明します。

Result とは何か?

Result は、実行結果について、結果の状態(成功/失敗)と 結果(計算結果)をまとめて扱うことができる enum です。

Swift の enum は、その中に値を保つことができるので、結果状態だけではなく、結果の値を保持することができます。

Result<Success,Error>とは何か

Result<Success, Error> と書くと、正常実行された際の結果 Success と エラーが発生した時の Error を保持するような Result という意味になります。

結果を保持するので、実行結果の状態に応じて、計算結果、エラー情報を取得することができます。

具体的には、Result<Int, Error>という方の Result に対して、以下のような switch 文を使って、結果をチェックすることができます。

Result の switch

Result を返す側では、以下のような書き方になります。

Result 生成コード

Result を使う利点とは?

実行結果状態だけではなく、結果も合わせて保持できることが1つ目です。

これまでの非同期処理では、引数に正常実行結果と合わせて、エラー情報を渡されて、その2つをチェックすることが多かったと思いますが、この情報を合わせた1つの Result が渡されることで、不整合を防ぎやすくなります。

また、Result の実装に、enum が使用されていることで、タイプチェックしやすくなるとともに、switch 等で判定するときにモレヌケが防止できます。

Playground で使ってみる

Playground 上で以下のコードを実行すると、感じがつかめる気がします。

example code

Result 応用編:非同期処理 の UI に使うケース

UI として、処理がうまくいったとき と うまくいかなかった時で 表示を切り替えることはよくあります。

Result で結果を保持することで、Result の .success, .failure の状態を表示の切り替えに使うことができます。

さらには、非同期の処理が使われていると、処理が正常終了した、処理が異常終了した 以外に、計算途中という状態も持ち得ます。

Result を ?(optional) という形で保持することで、計算途中という状態を持たせることも可能となります。

SwiftUI での Result 使用例

(1) エラー原因情報を含む MyuCustomStringConvertibleError を定義
(2) 起動時の画面を定義。値設定のスライダーと下位ビューへ遷移するためのボタンを表示
(3) 押下されるとステッパーで指定された値を下位ビューへ渡して遷移する
(4) NavigationLink で遷移する下位ビュー
(5) 非同期を想定した関数の実行結果を保持する Result の定義
(6) 保持している Result の状態によって、表示を切り替える switch 文
(7) Result が .success の状態であれば、結果を Text ビューで表示
(8) Result が .failure の状態であれば、エラーの詳細情報を Text ビューで表示
(9) Result が nil であれば、まだ計算が終了していないので、ProgressView を表示
ChildView へ遷移したときには、Result は nil なので、.onAppear を使用して、ChildView 遷移時に関数実行開始
(10) 実行される関数。非同期を想定しているので、3秒待ってから completion を呼ぶ
(11) 渡された値が 1 であれば、成功として 1 を返し、そうでなければ、”1 より大なのでエラー”、”1 より小なのでエラー”という情報を付与してエラーを返す

Work without error

「Work without error」

Work with Error

「Work with Error」

まとめ

Result の使い方
  • Result を使うと、実行状態(成功/失敗)と合わせて実行結果を渡すことができる
  • Result を生成するときには、.success と合わせて実行結果値、.failure と合わせて Error をセットする
  • 受け取った Result をチェックするときには、.success, .failure をチェックする。抜けもれは、Swift 側でチェックしてくれる
  • SwiftUI と組み合わせるときには、Result? としてオプショナルにすると、非同期処理と相性が良い

説明は以上です。
不明な点やおかしな点ありましたら、ご連絡いただけるとありがたいです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です