zoukankan      html  css  js  c++  java
  • iOS开发中<null>的处理

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

    问题:

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

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

    -[NSNull length]: unrecognized selector sent to instance

    解决方案:

    用了一个Category,叫做NullSafe 。

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

    NullSafe 源码:

    #import <objc/runtime.h>
    #import <Foundation/Foundation.h>
    
    
    #ifndef NULLSAFE_ENABLED
    #define NULLSAFE_ENABLED 1
    #endif
    
    
    #pragma GCC diagnostic ignored "-Wgnu-conditional-omitted-operand"
    
    
    @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上查看:

    https://github.com/nicklockwood/NullSafe

  • 相关阅读:
    (三)openwrt主Makefile解析
    (二)我的Makefile学习冲动&&编译过程概述
    openwrt修改flash大小
    (一)openwrt源码目录概述
    git_sop 脚本使用说明
    Openwrt LuCI模块练习详细步骤
    openwrt简单ipk生成及Makefile解释
    oracle中比较两表表结构差异和数据差异的方法
    C#泛型集合之Dictionary<k, v>使用技巧
    SQL语句添加,删除主键
  • 原文地址:https://www.cnblogs.com/jukaiit/p/5694822.html
Copyright © 2011-2022 走看看