18
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NSPredicate で BOOL 型プロパティをテストするときの落とし穴

Last updated at Posted at 2014-03-25

ある NSManagedObject のサブクラスが BOOL 型のプロパティ aBoolProperty を持つとする。このプロパティが偽であるかどうかをテストするとき、以下のような NSPredicate を書きたくなるかもしれない:

anObject.aBoolProperty = NO;
NSPredicate *isNO = [NSPredicate predicateWithFormat:@"aBoolProperty == NO"];
[isNO evaluateWithObject:anObject]; // => YES

(注: predicate には比較演算子が必要なので @"!aBoolProperty" とは書けない)

厳密に NO と比較したいならこれで構わないが、 aBoolProperty偽だが NO と一致しない 場合もあることに気をつけよう。

Core Data が内部的に扱う aBoolProperty の値は @YES または @NO または nil である。これは BOOL 型の getter メソッドを介してアクセスする限り問題にならないが、内部値を直接扱う predicate では nil != @NO であることに注意しなければならない。

[anObject setPrimitiveValue:nil forKey:@"aBoolProperty"];

// getter は内部値が nil なら偽を返す
NSAssert(!anObject.aBoolProperty, @"");

// predicate では nil は NO と一致しない
NSPredicate *isNO = [NSPredicate predicateWithFormat:@"aBoolProperty == NO"];
[isNO evaluateWithObject:anObject]; // => *NO*

これが望み通りの挙動でないなら、 NO と一致するかどうかではなく YES でないことをテストすればよい:

[anObject setPrimitiveValue:nil forKey:@"aBoolProperty"];
NSPredicate *isNO = [NSPredicate predicateWithFormat:@"aBoolProperty != YES"];
[isNO evaluateWithObject:anObject]; // => YES
18
18
0

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
18
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?