OC的nil, Nil, NSNull, NULL和nullptr. 以及josn转换后的(null)和<null>

nil

Defines the id of a null instance.
定义一个ID类型的空实例.
示例代码:
   NSString *someString = nil;
   NSURL *someURL = nil;
   id someObject = nil;
   if (anotherObject == nil) // do something

在objc.h中的定义:

#ifndef nil
# if __has_feature(cxx_nullptr)
#   define nil nullptr
# else
#   define nil __DARWIN_NULL
# endif
#endif

Nil

Defines the id of a null class.
定义一个空的类
Available in Mac OS X v10.0 through Mac OS X v10.4.
Declared in NSObjCRuntime.h.
Declared Inobjc.h
示例代码:
  Class someClass = Nil;
  Class anotherClass = [NSString class];

在objc.h中的定义:

#ifndef Nil
# if __has_feature(cxx_nullptr)
#   define Nil nullptr
# else
#   define Nil __DARWIN_NULL
# endif
#endif

NSNull

The NSNull class defines a singleton object used to represent null values in collection objects (which don’t allow nil values).
NSNull类定义了一个单例对象用于表示集合对象的空值
集合对象无法包含nil作为其具体值,如NSArray、NSSet和NSDictionary。相应地,nil值用一个特定的对象NSNull来表示。NSNull提供了一个单一实例用于表示对象属性中的的nil值。默认的实现方法中,dictionaryWithValuesForKeys:和setValuesForKeysWithDictionary:自动地将NSNull和nil相互转换,因此您的对象不需要进行NSNull的测试操作。

例子:

// 因为 nil 被用来用为集合结束的标志,所以 nil 不能存储在 Foundation 集合里。
NSArray *array = [NSArray arrayWithObjects:@"one", @"two", nil];

// 错误的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:nil forKey:@"someKey"];

// 正确的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSNull null] forKey:@"someKey"];

NSNull.h 中定义:

//  NSNull.h
#import <Foundation/NSObject.h>
@interface NSNull : NSObject <NSCopying, NSSecureCoding>
+(NSNull *)null;
@end
  • (NSNull *)null;

@end

NULL

These macros define null values for classes and instances.
NULL可以用在C语言的各种指针上,
示例代码:
  int *pointerToInt = NULL;
  char *pointerToChar = NULL;
  struct TreeNode *rootNode = NULL;

stddef.h 中定义:

// in stddef.h
#define NULL ((void*)0)

nullptr

C++11引入了新的关键字来代表空指针常数:nullptr,将空指针和整数0的概念拆开。 nullptr的类型为nullptr_t,能隐式转换为任何指针或是成员指针的类型,也能和它们进行相等或不等的比较。而nullptr不能隐式转换为整数,也不能和整数做比较。
为了向下兼容,0仍可代表空指针常数:

char* pc = nullptr;     // OK
int * pi = nullptr;     // OK
int    i = nullptr;     // error
foo(pc);           // 呼叫foo(char *)

参考

根据Clang 3.7 文档对__has_feature的描述: “__has_feature evaluates to 1 if the feature is both supported by Clang and standardized in the current language standard or 0 if not”,__has_feature(cxx_nullptr)是用来判断是否支持C++11中的nullptr特性的。在Objective-C中nil和Nil都是__DARWIN_NULL宏定义。按住CMD鼠标点击进入_types.h:

#ifdef __cplusplus
#ifdef __GNUG__
#define __DARWIN_NULL __null
#else /* ! __GNUG__ */
#ifdef __LP64__
#define __DARWIN_NULL (0L)
#else /* !__LP64__ */
#define __DARWIN_NULL 0
#endif /* __LP64__ */
#endif /* __GNUG__ */
#else /* ! __cplusplus */
#define __DARWIN_NULL ((void *)0)
#endif /* __cplusplus */

因为Objective-C不是C++代码,所以倒数第二行#define __DARWIN_NULL ((void )0)此时高亮,意味着最终nil和Nil本质都为((void )0)

区别

  1. NSNull 与 nil和Nil的区别在于, NSNull用于容器值时是合法的,而nil/Nil会产生crash;
  2. 向nil/Nil发送消息是合法的, 向NSNull发送消息会产生crash.
  3. NULL一般用于C类型的任何空值.

( null )和< null >

josn字符中的null通过NSJSONSerialization类转换后,可能产生( null )或< null >类型(测试中只见< null>,( null)是网友说的,测试中没有出现过):

int main() {
    NSString *num = @"[{\"status\":null,\"msg\":\"围栏清单查询异常\"}]";
    NSError *error;
    NSData *createdData = [num dataUsingEncoding:NSUTF8StringEncoding];
    id response=[NSJSONSerialization JSONObjectWithData:createdData options:NSJSONReadingMutableContainers error:&error];
    NSLog(@"Response= %@",response);
    return 0;
}

结果:

Response = ({
    msg = "\U56f4\U680f\U6e05\U5355\U67e5\U8be2\U5f02\U5e38";
    status = "<null>";
})

以下程序会产生crash:

NSString *status = [[response firstObject] valueForKey:@"status"];
if (!status || [status isEqualToString:@""]) {
    //do something...
    NSLog(@"test");
}

crash原因分析:
1. !status不能用于NSNull的空判断, 所以继续执行||后面的语句;
2. status是NSNull, 向它发送消息会产生crash.

josn转换后的( null )和< null >的空判断

#define isNullStr(var) ([var isKindOfClass:[NSNull class]] || var == nil || ([var isKindOfClass:[NSString class]] && var.length==0))

//假设status是<null>或(null)类型(即NSNull或nil类型)
if (isNullStr(status)) {
    //do something...
    NSLog(@"status is null.");
}

OC容器中NSNull和nil的区别

//假设status是<null>类型(即NSNull类型)
NSDictionary *dic = @{@"1":status}; //合法, 成功添加一个元素
NSString *nullStr = nil;
NSDictionary *dic2 = @{@"2":nullStr}; //crash
NSDictionary *dic3 = [NSDictionary dictionaryWithObjectsAndKeys:nullStr,nullStr, nil]; //元素个数为0,但不会产生crash.

参考链接

http://ios.itcast.cn/news/20141015/1633199713.shtml
http://www.cocoachina.com/ios/20150312/11312.html
http://blog.csdn.net/shenshen123jun/article/details/38315755

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值