Objective-Cには「null」に相当するものがnil, Nil, NULL, NSNullの4種類ある。それぞれの意味の説明はあったが、使い分けに踏み込んだ記事が少なかったのでメモ。
nil
- null オブジェクトを表す
- もっとも頻繁に使うnull
-
nil
にメッセージを送信してもnil
がreturnされる - Blocks は
copy
メソッドで retain count を増やすことがあるので、Blocks の null を表すにはnil
を使う(Which is the right one, nil or NULL, to mark “no Objective-C block”? – Stack Overflow)
// 初期化に失敗した時はnilが入る
SomeClass *myInstance = [[SomeClass alloc] initWithFailCode];
// 変数に代入
id hoge = nil;
NSObject *fuga = nil;
if (fuga) {
// false
}
if (!fuga) {
// true
}
if (fuga == nil) {
// true
}
// nilにメッセージを送信してもnilが返る
if ([fuga doSomething] == nil) {
// true
}
// ブロックを渡す時のnullオブジェクトはnilで渡す
[something setCompletionBlock:nil];
Nil
-
Nil
はnullクラスオブジェクトを表す
// クラスを取得する
Class something = [NSObject class];
// クラスの指定がnull
Class anything = Nil;
NULL
- C言語の
(void *)0
と同じ -
void*
型のnullとして使う
[objA addObserver:objB forKeyPath:@"hoge" options:NSKeyValueObservingOptionNew context:NULL];
NSNull
- nullであることを示す、シングルトンのインスタンス
- シングルトンの取得には
[NSNull null]
を実行する - インスタンスなので、
[NSNull null] == nil
はNO
(false) になる - NSArrayやNSDictionaryの値のように、nilを指定できないところでnullオブジェクトを表したい時に使う
NSDictionary *someVars =
@{
@"keyA" : @"abc",
@"keyB" : [NSNull null]
}
// 1. NSNullはシングルトンなのでisEqualで比較できる
if ([someVars[@"keyB"] isEqual:[NSNull null]]) {
// true
}
// 2.NSDictionary#objectForKeyは存在しないキーを指定するとnilを返す
if (someVars[@"keyC"] == nil) {
// true
}
// 1.と2.により、キーに値が存在するかどうかは2つの検査が必要
if (someVars[@"keyA"] != nil && ![someVars[@"keyA"] isEqual:[NSNull null]]) {
// nilではなく、NSNullでもない
// => true
}
参考資料
- nil / Nil / NULL / NSNull – NSHipster
- The comp.lang.objective-C FAQ listing 日本語訳
- Which is the right one, nil or NULL, to mark “no Objective-C block”? – StackOverflow
- nilにまつわるエトセトラ – Qiita