NSErrorとNSException

Posted on
iOS Objective-c Swift NSError NSException

Cocoaには、エラーが起きた時の対処方法として、NSErrorNSExceptionがあります。

NSErrorNSExceptionの使い分け

Non-recoverableなケースのみNSExceptionを使い、それ以外は原則としてNSErrorを使います。

NSExceptionを使うケースとしては、methodの引数がinvalidな時(コールバックが必須なのに、nilだったなど)です。引数のチェックに私はよくNSParameterAssertを使っています。

typedef void (^CompletionBlock)(NSArray *array, NSError *error);
- (void)someMethod:(CompletionBlock)callback
{
  NSParameterAssert(callback);

  // 処理
}

NSErrorの使い方

NSErrorに含まれる情報は大きく3つあります。

  1. domain
  2. code
  3. userInfo

domainは文字列、codeはenumで定義される事が多く、どの領域でエラーが起こったか識別するのに利用します。userInfoはNSDictionaryのインスタンスで、localizedDescriptionというメソッドを呼ぶと、エラーに関する記述が含まれている文字列を返します。この文字列は、エラーが起きた際に、ユーザーに見せる情報としてよく使います。

// objective-c
if (error) {
  NSLog(@"%@", [error localizedDescrition]);
}

// swift
if let newError = error {
  error.localizedDescription
}

NSErrorの作り方

Cocoaではなく自分のアプリ/ライブラリ由来のNSErrorを定義したい場合は、errorWithDomain:code:userInfo:を使います。

// objective-c
NSString *const ABCErrorDomain = @"com.example.abc";
[NSError errorWithDomain:ABCErrorDomain
                    code:1
                userInfo:nil];
// swift
let ABCErrorDomain = "com.example.abc"
NSError(domain: ABCErrorDomain, code: 1, userInfo: nil)

domainに関しては、リバースドメイン形式が推奨されています。

objective-cで書く場合、専用のheaderファイルとimplementationファイルを用意し、そこにNSErrorに関する定義をまとめます。

// ABCError.h
FOUNDATION_EXPORT NSString *const ABCErrorDomain;
typedef NS_ENUM(int, ABCErrorCode) {
  ABCSomeError
};

// ABCError.m
NSString *const WPYErrorDomain = @"com.example.abc";

cf