LoginSignup
310

More than 5 years have passed since last update.

NSErrorが便利すぎる件 Appleありがとう

Last updated at Posted at 2015-11-11

NSErrorを返す系のメソッドを使う機会って良くあると思いますが(通信,保存など)、NSErrorの引数にnil以外(エラー)の場合どうしたらいいか分からないということが多々あるのではないでしょうか?

「だって、NSErrorにどういう内容が返ってくるか分からないし、分かったとしても全てのパターンにおいてエラー処理書かないといけないの?」的な。

だからNSErrorにエラーが返ってきたら、何もしない。
落ちるか落ちないかは神のみぞ知る的な。

やっぱりそれじゃちょっとダメプログラマかなと思い、エラーメッセくらい出してあげるか、ということでNSErrorの仕様読んでたらとんでもなく便利なことに気づいたので共有します。

UIAlertViewに表示する内容を全部『日本語』で返してくれる

※ UIAlertViewはios8からdeprecatedなので注意してね、俺は面倒くさいからUIAlertViewでやってるけどね爆

NSErrorのプロパティを簡単にご紹介

・localizedDescription
  → エラーの概要
・localizedFailureReason
  → エラーが発生した理由
・localizedRecoverySuggestion
  → 復旧方法(NextAction)
・localizedRecoveryOptions
  → AlertViewに表示するボタンの名前
  
これ何が便利かというとこれ全部ローカライズして返してくれるというところです。
普通だと「エラーコードを見て、それに対するメッセージを記述したリストを用意して、そして他言語対応するなら言語毎に用意して…」的なことをやる必要があると思いますが、フレームワーク側でローカライズしてくれるので、NSErrorに入っているプロパティをそのままUIAlertViewに表示してやれば、 ローカライズ完了 ということになります。

オススメの方法

UIAlertViewに表示するメッセージのオススメの方法ですが、

UIAlerViewの[title]には復旧方法がかかれている[localizedRecoverySuggestion]を突っ込む。

UIAlertViewの[message]には
[localizedDescription]はエラーの概要といった感じで、[localizedFailureReason]はそれをも少し詳しくといった感じだったので、
[localizedFailureReason]を突っ込む。

UIAlertViewのボタンに設定する文言は
[localizedRecoveryOptions]と思ってしまいますが、これは配列で返ってくるため、そのまま突っ込んでしまうと、ボタンによる処理分けをする必要があります。
そうなると、[localizedRecoverySuggestion]の内容から判断し処理を書かなければなくなり一気に、やらないといけないことが増えるので嫌です。(いや、できればした方がいいですが…)

なので、ここは割り切ってエラーメッセージを出すだけにします。

かつ、
・localizedFailureReason
・localizedRecoverySuggestion
・localizedRecoveryOptions
この3つのプロパティはオプショナル型なので返ってくるかどうか解かりません。

それを踏まえて、実際のコード書きます。

面倒くさいエラー処理の応急処置

とりあえず、以下のように書いておけば最低限のエラー処理にはなってるかなという感じです。
どこでも使えるようにUIViewControllerのextensionとして定義したので、良ければコピペってください。

ShowErrorAlertExtension.swift
import UIKit

extension UIViewController {
    func showErrorAlert(error:NSError){
        var title:String!
        var message:String?
        var btnTitle:String!
        if error.localizedFailureReason == nil{
            message = error.localizedDescription
        }else{
            message = error.localizedFailureReason
        }
        if let suggestion = error.localizedRecoverySuggestion {
            title = suggestion
        }else{
            title = "error"
        }
        if let titles = error.localizedRecoveryOptions {
            btnTitle = titles[0]
        }else{
            btnTitle = "OK"
        }

        let alertView = UIAlertView(title: title, message: message, delegate: nil, cancelButtonTitle: btnTitle)
        alertView.show()
    }
}

実際に動かした、エラーの画面です。
これは、動画を連続でアルバム内に保存しようとした時に出たエラーです。
[書き込みを再試行]が言葉足らず感が否めないですが、これにプラスで文言を付け加えようとすると、自力でローカライズする必要が出てくるので、あえてやりません。

滅多に起きないという前提ですし、雰囲気伝わるのでいいのではないでしょうか。

スクリーンショット_2015_11_11_11_41.png

この設定も忘れずに

ローカライズしたことがあれば分かると思いますが、[Localizations]に追加した言語以外は英語で表示されるのでローカライズしたい言語を追加してください。
OtherViews_と_Piconnect_xcodeproj.png

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
310