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

时间: 2024-08-01 08:10:11

iOS开发中<null>的处理的相关文章

iOS开发——淫技篇&amp;iOS开发中各种淫技总结(六)

iOS开发中各种淫技总结(六) swift中指针的使用 在 Swift 中,指针都使用一个特殊的类型来表示,那就是 UnsafePointer<T>.遵循了 Cocoa 的一贯不可变原则,UnsafePointer<T> 也是不可变的.当然对应地,它还有一个可变变体,UnsafeMutablePointer<T>.绝大部分时间里,C 中的指针都会被以这两种类型引入到 Swift 中:C 中 const 修饰的指针对应 UnsafePointer (最常见的应该就是 C

ios开发中object-c中UTF-8 和 GBK 的 NSString 相互转化的方法

应用都要遇到一个很头疼的问题:文字编码,汉字的 GBK 和 国际通用的 UTF-8 的互相转化稍一不慎, 就会满屏乱码.下面介绍 UTF-8 和 GBK 的 NSString 相互转化的方法 NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000); char* c_test = "北京"; int nLen = strlen(c_test); NSS

iOS开发中如何将后台返回的时间转换为常见字串

在iOS开发中,经常需要从后台数据中获取时间,但是此时后台返回的时间格式经常是一串类似"123456789"的数字,此数字是1970年开始截至到现在的秒数,此时我们需要将其转换为可以用的格式. 模型中我定义了c_time属性,通过重写c_time的get方法中进行格式的转换. - (NSString *)c_time{ // 1.创建时间格式化类 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; // 2.设置时间

ios学习笔记之block在ios开发中的应用

一.什么是Blocks      Block是一个C级别的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似,但是其运行需要编译器和运行时支持,从ios4.0开始就很好的支持Block. 二.在ios开发中,什么情况下使用Block      Block除了能够定义参数列表.返回类型外,还能够获取被定义时的词法范围内的状态(比如局部变量),并且在一定条件下(比如使用__block变量)能够修改这些状态.此外,这些可修改的状态在相同词法范围内的多个block之间是共享的,即便出了该词法范围

深入理解 iOS 开发中的锁

来源:伯乐在线 - 夏天然后 链接:http://ios.jobbole.com/89474/ 点击 → 申请加入伯乐在线专栏作者 摘要 本文的目的不是介绍 iOS 中各种锁如何使用,一方面笔者没有大量的实战经验,另一方面这样的文章相当多,比如 iOS中保证线程安全的几种方式与性能对比.iOS 常见知识点(三):Lock.本文也不会详细介绍锁的具体实现原理,这会涉及到太多相关知识,笔者不敢误人子弟. 本文要做的就是简单的分析 iOS 开发中常见的几种锁如何实现,以及优缺点是什么,为什么会有性能上

iOS开发中遇到的一些问题及解决方案【转载】

iOS开发中遇到的一些问题及解决方案[转载] 2015-12-29 [385][scrollView不接受点击事件,是因为事件传递失败] // //  MyScrollView.m //  Created by beyond on 15/6/6. //  Copyright (c) 2015年 beyond.com All rights reserved. //  不一定要用继承,可以使用分类 #import "MyScrollView.h" #import "CoView.

iOS开发中的绘图-Quartz2D-

转载请注明出处:http://blog.csdn.net/whjForWork/article/details/44926763 什么是Quartz2D Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 作用 Quartz 2D能完成的工作 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成PDF 截图\裁剪图片 自定义UI控件 - Quartz2D在iOS开发中的价值 为了便于搭建美观的UI界面,iOS提供了UIKit框架,里面有各种各样的

iOS开发中GCD在多线程方面的理解

GCD为Grand Central Dispatch的缩写. Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法.在Mac OS X 10.6雪豹中首次推出,并在最近引入到了iOS4.0. GCD是一个替代诸如NSThread等技术的很高效和强大的技术.GCD完全可以处理诸如数据锁定和资源泄漏等复杂的异步编程问题. GCD可以完成很多事情,但是这里仅关注在iOS应用中实现多线程所需的一些基础知识. 在开始之前,需要理解是要提供给GCD队列的是代

ios开发中的4种数据持久化方式【二、数据库 SQLite3、Core Data 的运用】

               在上文,我们介绍了ios开发中的其中2种数据持久化方式:属性列表.归档解档.本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运用: 在本节,将通过对4个文本框内容的创建.修改,退出后台,再重新回到后台,来认识这两种持久化数据的方式.效果图如下[图1]: [图1 GUI界面效果图] [本次开发环境: Xcode:7.2     iOS Simulator:iphone6S plus   By:啊左]     一.数据库SQL