我正在检查数组是否为nil,如果是,我想将一些计数器变量设置为0,如果数组不是nil则设置为数组的长度。
NSUInteger count = 0;
if (self.someArray == nil) {
count = 0;
}
else {
count = self.someArray.count;
}
这正如预期的那样正常。但是,当我尝试做这样的事情时:
NSUInteger count = (self.someArray == nil) ? 0 : self.someArray.count
我收到[NSNull count] unrecognized selector
错误。但是,当我这样做时
([self.someArray isKindOfClass:[NSNull class]]) ? 0 : self.someArray.count`
看起来后者应该对我有用,但是有什么简单的我可以忽略吗? NSNull
适用于零的对象?为什么简单的nil检查在if语句中而不是在三元运算符中工作?
答案 0 :(得分:1)
self.someArray
是NSNull
个对象,而不是NSArray
个对象。
我怀疑你从JSON消息中获取了对象,并且在将它存储到你的类之前没有检查过它。
一旦你排序了;如果数组已设置,则此方法有效:
NSUInteger count = self.someArray.count;
答案 1 :(得分:1)
nil
真的是(void *)0
。 NSNull
是一个具有单个实例的类,您可以使用[NSNull null]
获取该实例。将消息发送到nil是合法且无害的,但是消息传递null受运行时类型检查的影响。
因此,让我们将数组初始化为NSNull对象。任何以这种方式开始的代码肯定会在运行时引起悲伤,但这正是您反序列化JSON时所发生的事情(它必须在
NSArray *array = (NSArray *)[NSNull null]; // evil cast, just to illustrate
if (array == 0)
NSLog(@"I will never execute");
else
NSLog(@"I will always execute. null is a pointer to the instance of NSNull");
if ([array isKindOfClass:[NSNull class]]) // true, of course
if (array == [NSNull null]) // true, null is a singleton
if (!array) // false, same as above
if (array == nil) // false, same as above, array points to an object
NSLog(@"CRASH on next line, because null doesn't respond to count");
if (array.count > 0) // crash
但是,如果我们尝试从更为良性nil
...
NSArray *array = nil;
// or NSArray *array; same thing, since compiler will init to 0x0 for you
if (array == 0)
NSLog(@"I will always execute");
else
NSLog(@"I will never execute");
if (!array) // true, same as above
if (array == nil) // true, of course
NSLog(@"No crash on next line");
if (array.count > 0)
NSLog(@"I will never execute");
最后一点很有意思。我们可以将计数消息发送到nil数组而不会受到惩罚。它回答0,好像数组是空的。真正发生的是我们可以发送任何消息给nil,结果总是零。
那你该怎么办?一个想法是接受self.array有时可能是== [NSNull null]
(这又与== nil
不同)。更好的解决方案是在赋值点捕获JSON-produce-NSNull条件,如此......
// I just finished deserializing some JSON to id someObject
self.someArray = (someObject.theArray == [NSNull null])? nil : someObject.theArray;
// anytime after, we can safely message the array
NSInteger theCount = self.someArray.count; // zero, if someArray is empty OR nil
// and even get objects from it, as long as it contains any
id someObject = (self.someArray.count)? [someArray lastObject] : nil;