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)
区别
- NSNull 与 nil和Nil的区别在于, NSNull用于容器值时是合法的,而nil/Nil会产生crash;
- 向nil/Nil发送消息是合法的, 向NSNull发送消息会产生crash.
- 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