Swift-Languageでのエラー処理


190

私はSwiftをあまり読みませんでしたが、例外はないことに気づきました。では、Swiftでエラー処理をどのように行うのでしょうか。誰かがエラー処理に関連する何かを見つけましたか?


1
Obj-C:oと同様にエラーメッセージが見つかりました
Arbitur

13
@Arbitur古き良きsegfault方法?
peko 2014年

SwiftでNSTimerを作成し、関数のスペルを間違えるとクラッシュし、メソッドが見つからないというエラーが表示されました:)
Arbitur

3
あなたは、この記事の手順に従って、スウィフトのためのtry-catchのサポートを追加することができます。medium.com/@_willfalcon/adding-try-catch-to-swift-71ab27bcb5b8
ウィリアム・ファルコン

@peko Swiftでsegfaultをどのように処理しますか?今のところ、それは可能ではないと思います。悲しいことに、いくつかのエラーは回復不能です
Orlin Georgiev

回答:


148

スウィフト2&3

Swift 2では、例外に多少似ていますが詳細が異なる新しいエラー処理メカニズムがあるため、状況が少し変更されています。

1.エラーの可能性を示す

関数/メソッドがエラーをスローする可能性があることを示したい場合は、throwsこのようなキーワードを含める必要があります

func summonDefaultDragon() throws -> Dragon

注:関数が実際にスローできるエラーのタイプの仕様はありません。この宣言は、関数がErrorTypeを実装する任意のタイプのインスタンスをスローできるか、まったくスローしないことを示しています。

2.エラーをスローする可能性のある関数の呼び出し

関数を呼び出すには、次のようにtryキーワードを使用する必要があります

try summonDefaultDragon()

この行は通常、このようなdo-catchブロックが存在する必要があります

do {
    let dragon = try summonDefaultDragon() 
} catch DragonError.dragonIsMissing {
    // Some specific-case error-handling
} catch DragonError.notEnoughMana(let manaRequired) {
    // Other specific-case error-handlng
} catch {
    // Catch all error-handling
}

注:catch句はSwiftパターンマッチングのすべての強力な機能を使用するため、ここでは非常に柔軟です。

それ自体がthrowsキーワードでマークされている関数からスロー関数を呼び出している場合は、エラーを伝播することを決定できます。

func fulfill(quest: Quest) throws {
    let dragon = try summonDefaultDragon()
    quest.ride(dragon)
} 

または、次を使用してスロー関数を呼び出すこともできますtry?

let dragonOrNil = try? summonDefaultDragon()

この方法では、エラーが発生した場合に戻り値またはnilを取得します。この方法を使用すると、エラーオブジェクトを取得できません。

つまり、次のtry?ような便利なステートメントと組み合わせることができます。

if let dragon = try? summonDefaultDragon()

または

guard let dragon = try? summonDefaultDragon() else { ... }

最後に、エラーが実際には発生しないことを確認して(たとえば、すでにチェック済みであることを前提としているため)、次のtry!キーワードを使用できます。

let dragon = try! summonDefaultDragon()

関数が実際にエラーをスローすると、アプリケーションでランタイムエラーが発生し、アプリケーションが終了します。

3.エラーを投げる

エラーをスローするには、次のようにthrowキーワードを使用します

throw DragonError.dragonIsMissing

ErrorTypeプロトコルに準拠したものは何でもスローできます。初心者のNSError場合、このプロトコルに準拠していますが、おそらく次のようなErrorType追加のデータを使用して、複数の関連エラーをグループ化できる列挙型ベースにしたいと思うでしょう。

enum DragonError: ErrorType {
    case dragonIsMissing
    case notEnoughMana(requiredMana: Int)
    ...
}

新しいSwift 2&3エラーメカニズムとJava / C#/ C ++スタイルの例外の主な違いは次のとおりです。

  • 構文は少し異なります:do-catch+ try+ defer従来のtry-catch-finally構文。
  • 例外処理では、通常、成功パスよりも例外パスの方が実行時間が長くなります。これは、成功パスとエラーパスのコストがほぼ同じであるSwift 2.0エラーの場合とは異なります。
  • エラーをスローするコードはすべて宣言する必要がありますが、例外はどこからでもスローされている可能性があります。すべてのエラーは、Javaの命名法では「チェックされた例外」です。ただし、Javaとは異なり、スローされる可能性のあるエラーを指定しません。
  • Swift例外はObjC例外と互換性がありません。きみのdo-catchあなたがにObjCを使用する必要があり、そのためにブロックは、任意のNSExceptionをキャッチし、その逆ではないでしょう。
  • Swiftの例外はNSErrorfalseBool関数を返す場合)またはnilAnyObject関数を返す場合)を返しNSErrorPointer、エラーの詳細を渡すというCocoa メソッドの規則と互換性があります。

エラー処理を容易にするための追加のsyntatic-sugarとして、さらに2つの概念があります。

  • 遅延アクション(使用 deferキーワード)。これにより、Java / C#/ etcの最終ブロックと同じ効果を達成できます。
  • guard通常のエラーチェック/シグナリングコードよりも少ないif / elseコードを記述できるガードステートメント(キーワードを使用)。

スウィフト1

ランタイムエラー:

Leandrosがランタイムエラー(ネットワーク接続の問題、データの解析、ファイルのオープンなど)を処理することを提案しているNSErrorように、Foundation、AppKit、UIKitなどがこの方法でエラーを報告するため、ObjCで行ったように使用する必要があります。つまり、言語のことよりもフレームワークのことです。

使用されている別の頻繁なパターンは、AFNetworkingのようなセパレーター成功/失敗ブロックです。

var sessionManager = AFHTTPSessionManager(baseURL: NSURL(string: "yavin4.yavin.planets"))
sessionManager.HEAD("/api/destoryDeathStar", parameters: xwingSquad,
    success: { (NSURLSessionDataTask) -> Void in
        println("Success")
    },
    failure:{ (NSURLSessionDataTask, NSError) -> Void in
        println("Failure")
    })

それでも、障害ブロックは頻繁にNSErrorインスタンスを受け取り、エラーを説明します。

プログラマエラー:

プログラマーエラー(配列要素の範囲外アクセス、関数呼び出しに渡される無効な引数など)の場合、ObjCで例外を使用しました。スウィフト言語は、例外のいずれかの言語サポートを持っていないようです(のようなthrowcatchなどのキーワード)。ただし、ドキュメントに示されているように、ObjCと同じランタイムで実行されているため、次のようにスローすることができますNSExceptions

NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()

ObjCコードで例外をキャッチすることを選択しても、純粋なSwiftではそれらをキャッチできません。

問題は、プログラマーのエラーに対して例外をスローすべきか、それともAppleが言語ガイドで提案しているようにアサーションを使用すべきかどうかです。


20
Cocoa API(NSFileHandle)を使用した「ネットワーク接続の問題」および「ファイルを開く」は、キャッチする必要のある例外をスローする可能性があります。Swiftで例外なく、プログラムのこの部分をObjective-Cに実装するか、BSD C APIを使用してすべての作業を実行する必要があります(どちらも不十分な回避策です)。より多くの...のためNSFileHandle.writeDataのドキュメントを参照してくださいdeveloper.apple.com/library/ios/documentation/Cocoa/Reference/...
マット・ギャラガー

5
繰り返しになりますが、例外処理は、すべての固有の問題を伴う2段階のオブジェクト構築を意味します。stroustrup.com/except.pdfを参照してください。
Phil

2
これfatalError(...)も同じです。
holex 2014年

8
私はSwiftが好きなだけで、これは破滅的な選択だと思います。結果のいくつかを味わったので、彼らはこの省略で火をつけています...
Rob

2
はい、チェック例外は控えめに使用されるようになりました。プログラマに例外をキャッチするよう強いることで、単一の責任の原則を破って汚染コードから回復することはほとんど期待できないことがわかりました。ドメインレベルのクラスは、インフラストラクチャレイヤーの例外を処理する必要はありません。したがって、現在、チェックされていない例外が優先される傾向があり、必要に応じて、利害関係者がそれらをキャッチできます。。チェック済み=確実に回復可能。オフ=回復不能/回復不能の可能性があります。
ジャスパーブルース

69

2015年6月9日更新-非常に重要

スウィフト2.0が付属していますtrythrowと、catchキーワードと最もエキサイティングです。

Swiftは、エラーを生成するObjective-Cメソッドを、Swiftのネイティブエラー処理機能に従ってエラーをスローするメソッドに自動的に変換します。

注:デリゲートメソッドや、NSErrorオブジェクト引数を持つ完了ハンドラーを取るメソッドなど、エラーを消費するメソッドは、Swiftによってインポートされたときにスローされるメソッドにはなりません。

抜粋:Apple Inc.「CocoaおよびObjective-CでのSwiftの使用(Swift 2プレリリース)」iBooks。

例:(本から)

NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *URL = [NSURL fileURLWithPath:@"/path/to/file"];
NSError *error = nil;
BOOL success = [fileManager removeItemAtURL:URL error:&error];
if (!success && error){
    NSLog(@"Error: %@", error.domain);
}

Swiftで同等のものは次のようになります。

let fileManager = NSFileManager.defaultManager()
let URL = NSURL.fileURLWithPath("path/to/file")
do {
    try fileManager.removeItemAtURL(URL)
} catch let error as NSError {
    print ("Error: \(error.domain)")
}

エラーを投げる:

*errorPtr = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCannotOpenFile userInfo: nil]

呼び出し元に自動的に伝達されます:

throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotOpenFile, userInfo: nil)

Appleの本、Swiftプログラミング言語によると、エラーは列挙型を使用して処理する必要があるようです。

これが本の例です。

enum ServerResponse {
    case Result(String, String)
    case Error(String)
}

let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")

switch success {
case let .Result(sunrise, sunset):
    let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
    let serverResponse = "Failure...  \(error)"
}

出典:Apple Inc.「The Swift Programming Language」iBooks。https://itun.es/br/jEUH0.l

更新

Appleのニュースブック、「CocoaおよびObjective-CでのSwiftの使用」から。Swift言語を使用してもランタイム例外は発生しないため、try-catchはありません。代わりに、オプションのチェーンを使用します

これが本の一部です。

たとえば、以下のコードリストでは、lengthプロパティとcharacterAtIndex:メソッドがNSDateオブジェクトに存在しないため、1行目と2行目は実行されません。myLength定数はオプションのIntであると推定され、nilに設定されます。3行目に示すように、if-letステートメントを使用して、オブジェクトが応答しない可能性のあるメソッドの結果を条件付きでアンラップすることもできます。

let myLength = myObject.length?
let myChar = myObject.characterAtIndex?(5)
if let fifthCharacter = myObject.characterAtIndex(5) {
    println("Found \(fifthCharacter) at index 5")
}

抜粋:Apple Inc.「CocoaおよびObjective-CでのSwiftの使用」iBooks。https://itun.es/br/1u3-0.l


また、Objective-C(NSErrorオブジェクト)のココアエラーパターンを使用することも推奨されています。

Swiftのエラー報告は、Objective-Cと同じパターンに従いますが、オプションの戻り値を提供するという利点もあります。最も単純なケースでは、関数からBool値を返し、それが成功したかどうかを示します。エラーの理由を報告する必要がある場合は、関数にNSErrorPointerタイプのNSError出力パラメーターを追加できます。この型は、Objective-CのNSError **とほぼ同じですが、追加のメモリ安全性とオプションの型指定があります。次のコードリストに示すように、プレフィックス&演算子を使用して、オプションのNSErrorタイプへの参照をNSErrorPointerオブジェクトとして渡すことができます。

var writeError : NSError?
let written = myString.writeToFile(path, atomically: false,
    encoding: NSUTF8StringEncoding,
    error: &writeError)
if !written {
    if let error = writeError {
        println("write failure: \(error.localizedDescription)")
    }
}

抜粋:Apple Inc.「CocoaおよびObjective-CでのSwiftの使用」iBooks。https://itun.es/br/1u3-0.l


最後の文の場合、それは次のようになりますか{myString.writeToFileを試してみてください(アトミック、パス:真、エンコード:NSUTF8StringEncoding)}キャッチすることはNSError {印刷(エラー)}としてエラーを聞かせて
ジャッキー

1
@Jackyはい、これはSwift 2.0に当てはまります。この回答はSwift 2.0のリリース前に書かれていましたが、Swift 2.0でエラーを処理する新しい方法を示すために回答を更新しました。私はこの方法を参考にするために考えていましたが、swift 2.0のみを使用するように回答全体を更新することを検討します
ギルヘルメトーレスカストロ

12

Objective-Cのアプローチと同様に、Swiftには例外はありません。

開発では、を使用assertして、表示される可能性があるエラーをキャッチし、本番環境に移行する前に修正する必要があります。

従来のNSErrorアプローチは変更されず、が送信されるが送信されますNSErrorPointer

簡単な例:

var error: NSError?
var contents = NSFileManager.defaultManager().contentsOfDirectoryAtPath("/Users/leandros", error: &error)
if let error = error {
    println("An error occurred \(error)")
} else {
    println("Contents: \(contents)")
}

6
これにより、2つの質問が生じます。Swiftから呼び出したObjCコードが実際に例外をスローするとどうなるか、そしてNSErrorがObjCのような普遍的なエラーオブジェクトかどうかです。
MDJ 2014年

1
イニシャライザが失敗しない、または失敗できないのは、Swiftでの現実の事実ですか?
Phil

11
例外処理はかなり汚い
Tash Pemhiwa

27
ええと、あなたがクラッシュするだけで例外が必要な人は?または、宣言するすべての関数の引数としてNSError **を入れますか?すべてf();g();f(&err);if(err) return;g(&err);if(err) return;最初の月になるように、それからちょうどそれになるf(nil);g(nil);hopeToGetHereAlive();
hariseldon78 '20

2
この答えは、(Objective-Cのサポート例外を行い時代遅れ(スウィフトは現在の例外をサポートしています)と間違って両方です。
Rogメール

11

推奨される「Swift Way」は次のとおりです。

func write(path: String)(#error: NSErrorPointer) -> Bool { // Useful to curry error parameter for retrying (see below)!
    return "Hello!".writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: error)
}

var writeError: NSError?
let written = write("~/Error1")(error: &writeError)
if !written {
    println("write failure 1: \(writeError!.localizedDescription)")
    // assert(false) // Terminate program
}

ただし、最後にエラー処理を別のブロックに移動するため、追跡が容易であるため、try / catchを使用します。この配置は、「ゴールデンパス」と呼ばれることもあります。ラッキーでこれをクロージャーで行うことができます:

TryBool {
    write("~/Error2")(error: $0) // The code to try
}.catch {
    println("write failure 2: \($0!.localizedDescription)") // Report failure
    // assert(false) // Terminate program
}

また、再試行機能を追加するのも簡単です。

TryBool {
    write("~/Error3")(error: $0) // The code to try
}.retry {
    println("write failure 3 on try \($1 + 1): \($0!.localizedDescription)")
    return write("~/Error3r")  // The code to retry
}.catch {
    println("write failure 3 catch: \($0!.localizedDescription)") // Report failure
    // assert(false) // Terminate program
}

TryBoolのリストは次のとおりです。

class TryBool {
    typealias Tryee = NSErrorPointer -> Bool
    typealias Catchee = NSError? -> ()
    typealias Retryee = (NSError?, UInt) -> Tryee

    private var tryee: Tryee
    private var retries: UInt = 0
    private var retryee: Retryee?

    init(tryee: Tryee) {
        self.tryee = tryee
    }

    func retry(retries: UInt, retryee: Retryee) -> Self {
        self.retries = retries
        self.retryee = retryee
        return self
    }
    func retry(retryee: Retryee) -> Self {
        return self.retry(1, retryee)
    }
    func retry(retries: UInt) -> Self {
        // For some reason you can't write the body as "return retry(1, nil)", the compiler doesn't like the nil
        self.retries = retries
        retryee = nil
        return self
    }
    func retry() -> Self {
        return retry(1)
    }

    func catch(catchee: Catchee) {
        var error: NSError?
        for numRetries in 0...retries { // First try is retry 0
            error = nil
            let result = tryee(&error)
            if result {
                return
            } else if numRetries != retries {
                if let r = retryee {
                    tryee = r(error, numRetries)
                }
            }
        }
        catchee(error)
    }
}

Bool値の代わりにオプションの戻り値をテストするための同様のクラスを作成できます。

class TryOptional<T> {
    typealias Tryee = NSErrorPointer -> T?
    typealias Catchee = NSError? -> T
    typealias Retryee = (NSError?, UInt) -> Tryee

    private var tryee: Tryee
    private var retries: UInt = 0
    private var retryee: Retryee?

    init(tryee: Tryee) {
        self.tryee = tryee
    }

    func retry(retries: UInt, retryee: Retryee) -> Self {
        self.retries = retries
        self.retryee = retryee
        return self
    }
    func retry(retryee: Retryee) -> Self {
        return retry(1, retryee)
    }
    func retry(retries: UInt) -> Self {
        // For some reason you can't write the body as "return retry(1, nil)", the compiler doesn't like the nil
        self.retries = retries
        retryee = nil
        return self
    }
    func retry() -> Self {
        return retry(1)
    }

    func catch(catchee: Catchee) -> T {
        var error: NSError?
        for numRetries in 0...retries {
            error = nil
            let result = tryee(&error)
            if let r = result {
                return r
            } else if numRetries != retries {
                if let r = retryee {
                    tryee = r(error, numRetries)
                }
            }
        }
        return catchee(error)
    }
}

TryOptionalバージョンでは、オプションではない戻り値の型が適用され、後続のプログラミングが容易になります(例: 'Swift Way:

struct FailableInitializer {
    init?(_ id: Int, error: NSErrorPointer) {
        // Always fails in example
        if error != nil {
            error.memory = NSError(domain: "", code: id, userInfo: [:])
        }
        return nil
    }
    private init() {
        // Empty in example
    }
    static let fallback = FailableInitializer()
}

func failableInitializer(id: Int)(#error: NSErrorPointer) -> FailableInitializer? { // Curry for retry
    return FailableInitializer(id, error: error)
}

var failError: NSError?
var failure1Temp = failableInitializer(1)(error: &failError)
if failure1Temp == nil {
    println("failableInitializer failure code: \(failError!.code)")
    failure1Temp = FailableInitializer.fallback
}
let failure1 = failure1Temp! // Unwrap

TryOptionalの使用:

let failure2 = TryOptional {
    failableInitializer(2)(error: $0)
}.catch {
    println("failableInitializer failure code: \($0!.code)")
    return FailableInitializer.fallback
}

let failure3 = TryOptional {
    failableInitializer(3)(error: $0)
}.retry {
    println("failableInitializer failure, on try \($1 + 1), code: \($0!.code)")
    return failableInitializer(31)
}.catch {
    println("failableInitializer failure code: \($0!.code)")
    return FailableInitializer.fallback
}

自動アンラップに注意してください。


7

編集:この答えは機能しますが、それはObjective-CがSwiftに文字変換されたものに過ぎません。Swift 2.0の変更により廃止されました。上記のGuilherme Torres Castroの回答は、Swiftでのエラー処理の推奨される方法の非常に優れた紹介です。VOS

それを理解するのに少し時間がかかりましたが、私はそれを理解したと思います。それは醜いようですが。Objective-Cバージョンの薄いスキンにすぎません。

NSErrorパラメータを使用して関数を呼び出しています...

var fooError : NSError ? = nil

let someObject = foo(aParam, error:&fooError)

// Check something was returned and look for an error if it wasn't.
if !someObject {
   if let error = fooError {
      // Handle error
      NSLog("This happened: \(error.localizedDescription)")
   }
} else {
   // Handle success
}`

エラーパラメータを取る関数を記述しています...

func foo(param:ParamObject, error: NSErrorPointer) -> SomeObject {

   // Do stuff...

   if somethingBadHasHappened {
      if error {
         error.memory = NSError(domain: domain, code: code, userInfo: [:])
      }
      return nil
   }

   // Do more stuff...
}


5

try catch機能を提供する目的Cの基本的なラッパー。 https://github.com/williamFalcon/SwiftTryCatch

次のように使用します:

SwiftTryCatch.try({ () -> Void in
        //try something
     }, catch: { (error) -> Void in
        //handle error
     }, finally: { () -> Void in
        //close resources
})

良いアイデア。ただし、これを使用することに決めた人は、例外がスローされたときにtryブロックで割り当てられたオブジェクトが割り当て解除されないことに注意する必要があります。これにより、ゾンビオブジェクトの問題が発生する可能性があり、RAIIのすべての使用が危険にさらされます(自動ロック解除、自動SQLコミット、自動SQLロールバック...)。たぶんc ++は何らかの形の「runAtExit」で私たちを助けることができるでしょうか?
hariseldon78 2014年

更新:例外がスローされたときにオブジェクトの解放を有効にするフラグが-fobjc-arc-exceptionsにあることがclangにあることがわかりました。ラップされたバージョンでも機能するかどうか試してみる必要があります(そうする必要があると思います)
hariseldon78

このオプションを使用する場合は、コンパイラーが半例外セーフコードを生成する必要があるため、コードサイズが大きくなることに注意してください。また、そのようなコンパイラー機能に依存することは最善のアイデアではない場合があります。例外はプログラマーのエラー専用であるため、開発中にわずかなメモリを節約するためだけにコンパイラオプションを調整することは価値がありません。プロダクションコードに例外がある場合は、最初にそれらの例外の原因に対処する必要があります。
クリスチャンキエンレ2014

1
あなたの手に負えない状況があるかもしれません。たとえば、jsonを間違った形式で解析しています。
ウィリアムファルコン

3

これは、swift 2.0のアップデートの回答です。Javaのような機能豊富なエラー処理モデルを楽しみにしています。最後に、彼らは良いニュースを発表しました。ここに

エラー処理モデル:Swift 2.0の新しいエラー処理モデルは、慣れ親しんだtry、throw、catchキーワードを使用して、即座に自然に感じられます。何よりも、Apple SDKおよびNSErrorと完全に連携するように設計されています。実際、NSErrorはSwiftのErrorTypeに準拠しています。詳細については、Swiftの新機能に関するWWDCセッションをぜひご覧ください。

例:

func loadData() throws { }
func test() {
do {
    try loadData()
} catch {
    print(error)
}}

3

ギリェルメトーレスカストロが言ったように、スイフト2.0で、trycatchdoプログラミングに使用することができます。

たとえば、CoreDataでは、データメソッドをフェッチする代わりに &errorにパラメータとしてmanagedContext.executeFetchRequest(fetchRequest, error: &error)、今、私たちは使用のみを使用する必要がありmanagedContext.executeFetchRequest(fetchRequest)、その後でエラーを処理しtrycatchAppleのドキュメントリンク

do {
   let fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as? [NSManagedObject]
   if let results = fetchedResults{
      people = results
   }
} catch {
   print("Could not fetch")
}

xcode7ベータ版を既にダウンロードしている場合。ドキュメントとAPIリファレンススローエラーを検索してみてください、最初に表示される結果を選択して。これにより、この新しい構文で実行できることの基本的なアイデアが得られます。ただし、完全なドキュメントはまだ多くのAPIに投稿されていません。

より洗練されたエラー処理技術は、

Swiftの新機能(2015セッション106 28分30秒)



1

例外を処理するための素晴らしくシンプルなlib: TryCatchFinally-Swift

他のいくつかのように、客観的なC例外機能をラップします。

次のように使用します。

try {
    println("  try")
}.catch { e in
    println("  catch")
}.finally {
    println("  finally")
}

サンプルを追加しました:)
Morten Holmgaard

それはおそらく著者の意見に言及する価値があります:「警告:これは楽しさと悪のためのハックです。それを使用する誘惑に抵抗してください。」
jbat100

1

Swift 2以降では、他の人がすでに述べたように、エラー処理はdo / try / catchおよびErrorType列挙型を使用することで最適に実行されます。これは同期メソッドの場合は非常にうまく機能しますが、非同期エラー処理には少し賢いことが必要です。

この記事には、この問題に対する優れたアプローチがあります。

https://jeremywsherman.com/blog/2015/06/17/using-swift-throws-with-completion-callbacks/

要約する:

// create a typealias used in completion blocks, for cleaner code
typealias LoadDataResult = () throws -> NSData

// notice the reference to the typealias in the completionHandler
func loadData(someID: String, completionHandler: LoadDataResult -> Void)
    {
    completionHandler()
    }

次に、上記のメソッドの呼び出しは次のようになります。

self.loadData("someString",
    completionHandler:     
        { result: LoadDataResult in
        do
            {
            let data = try result()
            // success - go ahead and work with the data
            }
        catch
            {
            // failure - look at the error code and handle accordingly
            }
        })

これは、非同期関数に個別のerrorHandlerコールバックを渡すよりも少しきれいに見えます。これは、Swift 2以前ではこれがどのように処理されるかでした。


0

私が見たことは、デバイスの性質上、ユーザーに一連の不可解なエラー処理メッセージを投げたくないということです。そのため、ほとんどの関数がオプションの値を返すので、オプションを無視するようにコーディングするだけです。関数がnilに戻って失敗した場合は、メッセージなどをポップできます。


1
nilを返すと、エラーの性質に関する情報は返されません。エラーが発生したときにエラーオブジェクトが返された場合、エラーに応じて、プログラマはそれを無視するか、処理するか、バブルアップさせるか、「メッセージなどをポップする」かを選択できます。知識は力である。
Vince O'Sullivan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.