从一开始做项目我就觉得服务器返回的数据很有问题,一般是这样的<null>。
返回的数据一空,程序就会crash。然后我也crash了。
问了许多人,没人碰到这种情况,好像他们的服务器没返回过<null>似的。
我国的大百度,搜点啥也特费劲。
我就一直很恶心的写了这样的代码:
if ([[[dic objectForKey:@"data"] objectForKey:@"nickname"] isEqual: [NSNull null]])
直到后来我发现了这样的代码:
#define NSNullObjects @[@"",@0,@{},@[]]
@interface NSNull (InternalNullExtention)
@end
@implementation NSNull (InternalNullExtention)
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
for (NSObject *object in NSNullObjects) {
signature = [object methodSignatureForSelector:selector];
if (signature) {
break;
}
}
}
return signature;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
SEL aSelector = [anInvocation selector];
for (NSObject *object in NSNullObjects) {
if ([object respondsToSelector:aSelector]) {
[anInvocation invokeWithTarget:object];
return;
}
}
[self doesNotRecognizeSelector:aSelector];
}
@end
立马高大上了。
这个原理就是如果实例本身就有相应的response,那么就会相应之,如果没有系统就会发出methodSignatureForSelector消息,寻问它这个消息是否有效?有效就返回对应的方法地址之类的,无效则返回nil。如果是nil就会crash, 如果不是nil接着发送forwardInvocation消息。所以我们在重写methodSignatureForSelector的时候就人工让其返回有效实例。
看看我是怎么试的:
NSDictionary * dict = (NSDictionary *)[NSNull null];
NSString * objectForKey = [dict objectForKey:@"str"];
NSLog(@"dict - %@",dict);
NSLog(@"objectForKey - %@",objectForKey);
打印日志:
2014-09-05 11:04:47.151 createData[797:60b] dict - <null>
2014-09-05 11:04:47.152 createData[797:60b] objectForKey - (null)
以后导入这个Category就可以解决判空的问题了!!!!!
其实再深入想想,是不是可以将对象找不到的消息动态转移到其他消息上。我再研究研究。