iOS开发中<null>的处理

来源:互联网 发布:七天网络登录入口注册 编辑:程序博客网 时间:2024/05/05 05:38

在iOS开发过程中经常需要与服务器进行数据通讯,JSON就是一种常用的高效简洁的数据格式。

问题:

在项目中,一直遇到一个坑的问题,程序在获取某些数据之后莫名崩溃。原因是:由于服务器的数据库中有些字段为空,然后以JSON形式返回给客户端时就会出现这样的数据:repairs = “”

这个数据类型不是nil 也不是 String。 解析成对象之后,如果直接向这个对象发送消息(eg:length,count 等等)就会直接崩溃。提示错误为:

-[NSNull length]: unrecognized selector sent to instance

解决方案:

用了一个Category,叫做NullSafe 。

NullSafe思路:在运行时操作,把这个讨厌的空值置为nil,而nil是安全的,可以向nil对象发送任何message而不会奔溃。这个category使用起来非常方便,只要加入到了工程中就可以了,你其他的什么都不用做,很简单。

NullSafe 源码:

#import "NSNull+NullSafe.h"#import <objc/runtime.h>#ifndef NULLSAFE_ENABLED#define NULLSAFE_ENABLED 1#endif@implementation NSNull (NullSafe)#if NULLSAFE_ENABLED- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector{    @synchronized([self class]){        //look up method signature        NSMethodSignature *signature = [super methodSignatureForSelector:selector];        if (!signature){            //not supported by NSNull, search other classes            static NSMutableSet *classList = nil;            static NSMutableDictionary *signatureCache = nil;            if (signatureCache == nil){                classList = [[NSMutableSet alloc] init];                signatureCache = [[NSMutableDictionary alloc] init];                //get class list                int numClasses = objc_getClassList(NULL, 0);                Class *classes = (Class *)malloc(sizeof(Class) * (unsigned long)numClasses);                numClasses = objc_getClassList(classes, numClasses);                //add to list for checking                NSMutableSet *excluded = [NSMutableSet set];                for (int i = 0; i < numClasses; i++){                    //determine if class has a superclass                    Class someClass = classes[i];                    Class superclass = class_getSuperclass(someClass);                    while (superclass){                        if (superclass == [NSObject class]){                            [classList addObject:someClass];                            break;                        }                        [excluded addObject:NSStringFromClass(superclass)];                        superclass = class_getSuperclass(superclass);                    }                }                //remove all classes that have subclasses                for (Class someClass in excluded){                    [classList removeObject:someClass];                }                //free class list                free(classes);            }            //check implementation cache first            NSString *selectorString = NSStringFromSelector(selector);            signature = signatureCache[selectorString];            if (!signature){                //find implementation                for (Class someClass in classList){                    if ([someClass instancesRespondToSelector:selector]){                        signature = [someClass instanceMethodSignatureForSelector:selector];                        break;                    }                }                //cache for next time                signatureCache[selectorString] = signature ?: [NSNull null];            }else if ([signature isKindOfClass:[NSNull class]]){                signature = nil;            }        }        return signature;    }}- (void)forwardInvocation:(NSInvocation *)invocation{    invocation.target = nil;    [invocation invoke];}#endif@end

详细的请去Github上查看,点击阅读原文

0 0