在Objective C中,一种常见的做法是经常放弃检查nil,而是依赖于消息无法无声地失败的事实。
例如,要验证字符串:
if ([myString length] > 1) { // Short and sweet
如果myString
为零,则此检查将失败 - 如预期的那样。这是一个巨大的改进,超出人们可能认为正确的实现,明确检查nil:
if (myString && [myString length] > 1) { // Redundant nil check
但是,特别是在Web API的情况下,myString可以设想为等于[NSNull null]
- 类似于nil,但具有不同的行为。主要关注的是,消息传递NSNull会导致异常。例如,我们之前的简短解决方案将导致异常:
// Causes an exception, because [NSNull null] is an object
NSString *myString = (id)[NSNull null];
if ([myString length] > 1) {
为了使事情更复杂,一个简单的零检查实际上会传递,因为[NSNull null]
是一个有效的对象:
NSString *myString = (id)[NSNull null];
if (myString) { // Evals to YES
因此,完全安全的唯一方法是通过调用方法检查NSNull 和执行常规隐式nil检查:
if (myString != (id)[NSNull null] && [myString length] > 1) { // Short and sweet
我的问题:这真的有必要吗?是否有更简洁的选项,重复代码更少,我忽略了?事实上,我的结论是否正确?
答案 0 :(得分:3)
NSNull对象通常会在人们阅读包含空值的JSON文件时出现。
在这种情况下,提供null值的服务器有可能认为你应该做一些与没有值不同的事情。例如,如果你得到一个字典并且某个键下可能存在一个字符串,你可能会得到一个长度非零的字符串,你可能会得到一个空字符串,因为服务器发送了一个空字符串,你可能什么也得不到,因为服务器什么都没发送给你,或者你可能得到[NSNull null],因为服务器发送了一个空值。由你决定是否需要区别对待空字符串,空字符串和[NSNull null]。
顺便说一句:我总是使用NSDictionary类的一些扩展,例如 - (NSString *)stringForKey,它将返回NSString或nil,100%保证。如果这样做,所有错误检查都在一种方法中。你可以做一些事情,比如将NSNumber转换为NSString,或者将NSNull转换为nil,或者将NSDictionary转换为nil,并且再也不用担心它。当然,你需要检查它是否合适。
答案 1 :(得分:2)
这真的有必要吗?
如果某些API可以返回NSNull
而不是字符串,那么是的,您应该检查它。它通常不是必需的,因为NSNull
不是一个字符串,并且大多数方法都不会返回一个字符串。但是,例如字典之类的集合可以将任何对象作为值。如果您不确定该值是否为字符串,则应采取适当的预防措施。
有没有更好的方法来处理我忽略的NSNull的可能性?
另一种可以做大致相同但保护自己免受其他类型(例如NSNumber
)的方法是检查你得到的东西的类型,而不是专门针对{{1}进行比较}:
[NSNull null]
答案 2 :(得分:1)
除了其他答案之外,在将API响应解析为模型对象之前,您可以考虑replacing NSNull instances with empty strings。类似地,您可以遍历响应字典的可变副本并删除其值包含NSNull的键。
基本上,当你收到回复时,请事先做好,这样你的代码就不会受到NSNull检查的影响。
答案 3 :(得分:0)
另一种解决方法是使用类别:
@interface NSNull (Utilities)
- (NSString *)stringValue;
@end
@implementation NSNull (Utilities)
- (NSString *)stringValue
{
return nil;
}
@end
然后简单地:
[myDictionary[@"key"] stringValue] // returns nil for NSNull values