この記事はObjective-C版の記事です。swift2版の記事を書きました
>> [iOS] swift2でもエラーハンドリングしたい NSError, do catch
ここから元記事です
==========================================
こんにちは。きんくまです。
今回はエラーと例外について知りたかったので調べてみました。
まず、こちらのページに書いてありました。
引用してあるAppleのドキュメントからこんな感じにまとめられるかと。
エラー NSError | 例外 NSException |
---|---|
ユーザーに関係するエラー。実行時におきる。 例えば、文字の入力に関してだとか、ネットワークの状況だとか。 |
プログラマーに関係するエラー。 配列のインデックスを範囲外にしてしまったり、メソッドの引数の数を間違えてしまったりとか。 アプリを出荷前になんとかしておく必要がある。 |
なので、エラーと例外は明確に区別する必要があるそうです。
というわけで、エラーのドキュメントをざっくり読んでみる。
> Introduction to Error Handling Programming Guide For Cocoa
エラーに設定するのは主に3つ
1) ドメイン
2) エラーコード
3) UserInfoのDictionary
1) ドメインは com.company.framework_or_app.ErrorDomain の形にする文字列
カテゴリ分けみたいなものだと思う。同じエラーコードでもドメインが違えば違うエラーと認識できる。
2) エラーコードは NSIntegerで定義
3) UserInfoのDictionary
ここに、エラーの概要、復旧方法を書いておく。
初期設定でDictionaryのkeyがいくつか定義されている。
最低必要そうなのをあげてみる。
・NSLocalizedDescriptionKey(概要)
・NSLocalizedRecoverySuggestionErrorKey(復旧方法)
エラーオブジェクトを作ってあげたあとは、どうやってそれを渡してあげるか考えます。
いろんな方法があると思うのですが、
1) Delegateパターンを使って、NSErrorを引数にするメソッドから渡す方法
2) 関数そのものにNSErrorのポインタのポインタを渡してあげて、エラーがあったらそこに入れてあげる方法
というのがあります。どちらもCocoaではよく使ってますね。
で、以上のものをふまえてサンプルを作ってみました。
今回は、0で数を割ろうとすると、エラーを出すクラスです。
KKFloatDivider.h
#import <Foundation/Foundation.h> FOUNDATION_EXPORT NSString *const KKFloatDividerErrorDomain; typedef enum : NSInteger{ KKFloatDividerErrorZeroDivide }KKFloatDividerErrorCode; @interface KKFloatDivider : NSObject - (CGFloat)divideFloatA:(CGFloat)floatA byFloatB:(CGFloat)floatB error:(NSError **)anError; @end
KKFloatDivider.m
#import "KKFloatDivider.h" NSString *const KKFloatDividerErrorDomain = @"com.kumade.handleErrorSample.KKFloatDividerErrorDomain"; @implementation KKFloatDivider - (CGFloat)divideFloatA:(CGFloat)floatA byFloatB:(CGFloat)floatB error:(NSError **)anError { if(floatB == 0){ if(anError != NULL){ NSDictionary *errorDic = @{ NSLocalizedDescriptionKey:@"Number cannot be divided by zero.", NSLocalizedRecoverySuggestionErrorKey:@"You can set numberB except zero" }; *anError = [[NSError alloc] initWithDomain:KKFloatDividerErrorDomain code:KKFloatDividerErrorZeroDivide userInfo:errorDic]; } return CGFLOAT_MAX; } return floatA / floatB; } @end
実際に別のオブジェクトから使ってみます。
- (IBAction)buttonTapped:(id)sender { CGFloat floatA = 5.3; CGFloat flaotB = 0; KKFloatDivider *divider = [[KKFloatDivider alloc] init]; NSError *error = nil; CGFloat result = [divider divideFloatA:floatA byFloatB:flaotB error:&error]; if(error){ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:error.localizedDescription message:error.localizedRecoverySuggestion delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; return; } NSLog(@"floatA / floatB = %f", result); }
今回は、エラーオブジェクトのUserInfoから取り出した概要、復旧方法を使ってUIAlertViewを作りました。
これでエラー処理になんとか対処できそうです。
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ