Resultについて
2021年03月09日
APIにアクセスし結果を返すような Errorも合わせて返すような場合に使用 します
Result型は以下のように定義されています
public enum Result<Success, Failure> where Failure : Error {
case success(Success)
case failure(Failure)
}
例えば、アプリ起動時にAPIにアクセスしたと仮定し、
データの取得に成功/失敗した場合で返す値を分けるのを Result
を使って書くと以下のようになります
/// 返す結果のモデル
struct User {
let id: Int
let name: String
}
/// Errorに準拠したenumを定義する必要がある
enum AppError: Error {
case networkError
case calcError
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// アプリ起動時によばれるメソッド
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
loadUser(canLoadData: false, handler: { result in
switch result {
case .success(let user):
print(user)
// => canLoadDataがtrueの場合、 User(id: 1, name: "taro")
case .failure(let error):
print(error)
// => canLoadDataがfalseの場合、 networkError
}
})
return true
}
/// canLoadDataがtrueの場合成功を想定した値を、falseで失敗を想定した場合の値を返す
private func loadUser(canLoadData: Bool, handler: (Result<User, AppError>) -> Void ) {
let user = User(id: 1, name: "taro")
// APIにアクセスしたと仮定し、データの取得成功/失敗の結果で返す値を変える
canLoadData ? handler(.success(user)) : handler(.failure(AppError.networkError))
}
}
使用方法
使用する時以下2つを意識します
Succes
には 結果として返したい型 を定義Failure
には Errorに準拠したenum を用意
Result型を定義する
1. Errorに準拠した型を用意
まず Error
に準拠した型を用意します
enum AppError: Error {
case networkError
case calcError
}
2. ResultでSuccessを使う
Success
で文字列型を返すResult型を使う場合
func loadResult() -> Result<String, AppError> {
return Result<String, AppError>.success("hello world!")
}
省略して書くことも出来ます
func loadResult() -> Result<String, AppError> {
return .success("hello world!")
}
3. ResultでFailureを使う
Failure
でAppError型を返すResult型を使う場合
func loadResult() -> Result<String, AppError> {
return Result<String, AppError>.failure(AppError.networkError)
}
省略して書くことも出来ます
func loadResult() -> Result<String, AppError> {
return .failure(.networkError)
}
例えば isSuccess
というフラグに応じて成功/失敗の別のResult型を返す場合以下のようになります
func loadResult(isSuccess: Bool) -> Result<String, AppError> {
// isSuccessに応じて成功/失敗のResultを返す
return isSuccess ? .success("hello world!") : .failure(.networkError)
}
Result型を使う
以下のように関数を定義した場合、
func loadResult(isSuccess: Bool) -> Result<String, AppError> {
// isSuccessに応じて成功/失敗のResultを返す
return isSuccess ? .success("hello world!") : .failure(.networkError)
}
使用する側では以下のように使います
let result: Result<String, AppError> = loadResult(isSuccess: true)
switch result {
case .success(let str):
print(str)
// => "hello world!"
case .failure(let error):
print(error)
// => networkError
}