我尝试了一些类似的东西:
if(myString != nil && myString.length) { ... }
并得到:
-[NSNull 长度]:发送到实例的无法识别的选择器
第一个条件失败后Objective-C不会短路吗?
我尝试了一些类似的东西:
if(myString != nil && myString.length) { ... }
并得到:
-[NSNull 长度]:发送到实例的无法识别的选择器
第一个条件失败后Objective-C不会短路吗?
Objective-C 确实支持短路评估,就像 C 一样。
似乎在您的示例myString
中 isNSNull
和 not nil
,因此myString != nil
是正确的。
NSNull是一个单例,用于表示nil
只允许对象的位置,例如在 NSArray 中。
顺便说一句,通常人们会写if (!myString && myString.length == 0)
. 对比起来nil
就很丑了。另外,我会将长度与 0 进行比较。这似乎更清楚。
Objective-C 是 C 的严格超集。
因为 C 支持短路评估,Objective-C 也支持。
NSNull 定义为什么?如果它是一个不代表什么的对象,那么它就不会是 nil。换句话说,NSNull 和 nil 是不一样的。
如果您在某处有 NSNull,您可能正在使用 JSON 解析器或 CoreData。当未设置 CoreData 中的数字时,CoreData 将返回 NSNull - CoreData 中的 NSString 值也可能相同。
同样,您可以在从服务器返回的 JSON 中包含空元素,并且某些解析器会将其作为 NSNull 对象提供给您。所以在这两种情况下,你在使用值时都必须小心,因为你认为是 NSString 或 NSNumber 对象的东西实际上是 NSNull。
一种解决方案是在 NSNull 上定义一个类别,该类别简单地忽略所有发送到对象的未理解消息,如下面的代码所示。然后您的代码将起作用,因为 NSNull.length 将返回 0。您可以在项目的 .pch 文件中包含类似的内容,该文件将包含在项目中的每个文件中。
// NSNull+IgnoreMessages.h
@interface NSNull(IgnoreMessages)
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
@end
//NSNull+IgnoreMessages.m
#import "NSNull+IgnoreMessages.h"
@implementation NSNull(IgnoreMessages)
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ( [self respondsToSelector:[anInvocation selector]] )
[anInvocation invokeWithTarget:self];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *sig=[[NSNull class] instanceMethodSignatureForSelector:aSelector];
// Just return some meaningless signature
if(sig==nil)
sig=[NSMethodSignature signatureWithObjCTypes:"@^v^c"];
return sig;
}
@end