如何处理NSNull值

时间:2014-12-16 16:38:36

标签: ios objective-c

在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

我的问题:这真的有必要吗?是否有更简洁的选项,重复代码更少,我忽略了?事实上,我的结论是否正确?

4 个答案:

答案 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