我尝试了以下几点:
if(myString != nil && myString.length) { ... }
得到了:
- [NSNull length]:发送到实例的无法识别的选择器
第一个条件失败后,Objective-C不会短路吗?
答案 0 :(得分:30)
Objective-C支持短路评估,就像C一样。
在您的示例中myString
似乎是NSNull
而不是nil
,因此myString != nil
是真的。
NSNull是一个单例,用于表示只允许对象的nil
,例如在NSArray中。
if (!myString && myString.length == 0)
。与nil
相比非常难看。另外,我将长度与0进行比较。这似乎更清楚。
答案 1 :(得分:10)
Objective-C是C的严格超集。
因为C支持短路评估,所以Objective-C也可以。
答案 2 :(得分:3)
NSNull定义为什么?如果它是一个应该代表什么的对象,那么它就不会是零。换句话说,NSNull和nil不一样。
答案 3 :(得分:0)
如果你有某个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