ErrorTypeをNSErrorにキャストするとuserInfoが消えてしまう問題の対策

Swiftを使い始めてそろそろ4w位経ちますが、まだまだ細かく引っかかることが多くて若干発狂気味なわたなべです。

今開発中のアプリで使う為に、Swift2+Alamofire+PromiseKit3でアプリの基盤的なものを作っているのですが、ErrorTypeをNSErrorにキャストするとuserInfoが消えてしまう問題が発生したので今回とった対策のメモ

以下のようにPromiseKitから受け取る error は ErrorType(実態はNSError)なので、userInfoを参照できるようにNSError型の変数に代入するとuserInfoが消えてしまいます。

do {
    try RestAPI.post(data)
        .then { (response: Foo) -> Void in
            debugPrint(response)
        }.error { (error) -> Void in
            let err: NSError = error as NSError // これでerr.userInfo が消える...
        }
} catch let error as NSError {
    // Error
}

色々調べた結果以下のようにすることでNSErrorにキャスト出来るようです。

    ((error as Any) as! NSError).localizedDescription

毎回キャストするのは面倒なのでこんな extension を作って対応しました。(作ったってほどのものじゃないけど...)

extension ErrorType {
    func nserror() -> NSError {
        return ((self as Any) as! NSError)
    }
}

このextensionを使えばこんな感じにかけてちょっとスッキリしました。

do {
    try RestAPI.post(data)
        .then { (response: Foo) -> Void in
            debugPrint(response)
        }.error { (error) -> Void in
            debugPrint(error.nserror().userInfo)
        }
} catch let error as NSError {
    // Error
}

Swift2はまだまだはまることも多いですが、Objective-Cと比べて格段にコード量は減るし便利なことも沢山あるのでいい感じです。早く使いこなせるようにならないとねー。

参考

Swift 2標準ガイドブック

Swift 2標準ガイドブック

stackoverflow.com