用Runtime中转发消息的方式解决服务器端返回NSNULL的问题

来源:互联网 发布:python re.compile用法 编辑:程序博客网 时间:2024/06/06 18:40

http://www.jianshu.com/p/7f937ed1e132

有时候服务器很烦不靠谱,老是不经意间返回null,所以在iOS端不得不校验它的类型等。譬如:返回的数组为null,首先得判断类型是不是NSArray 还得判断非空。

NSArray *products = data[@"省心宝"];if ([products isKindOfClass:[NSArray class]] && products.count > 0){    // TO DO}

这种问题一多,就会影响我们程序猿的心情,并且代码也变得冗余了,所以换种技巧solve it。

思路:重写NSNull的消息转发方法, 让他能处理这些异常的方法。
常见的几种类型为"",0,{},[]了。
所以,创建一个NSNull的分类 NSNull (InternalNullExtention)

具体实现如下:
.h文件

#import <Foundation/Foundation.h>@interface NSNull (InternalNullExtention)@end

.m文件

#import "NSNull+InternalNullExtention.h"#define NSNullObjects @[@"",@0,@{},@[]]@implementation NSNull (InternalNullExtention)+ (void)load{     @autoreleasepool {           [self swizzleInstanceMethodWithClass:[NSNull class] originalSel:@selector(methodSignatureForSelector:) replacementSel:@selector(wt_methodSignatureForSelector:)];           [self swizzleInstanceMethodWithClass:[NSNull class] originalSel:@selector(forwardInvocation:) replacementSel:@selector(wt_forwardInvocation:)];     }}- (NSMethodSignature *)wt_methodSignatureForSelector:(SEL)aSelector{     NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];     if (!signature) {          for (NSObject *object in NSNullObjects) {               signature = [object methodSignatureForSelector:aSelector];               if (!signature) {                    continue;               }               if (strcmp(signature.methodReturnType, "@") == 0) {                      signature = [[NSNull null] methodSignatureForSelector:@selector(wt_nil)];               }               return signature;          }          return [self wt_methodSignatureForSelector:aSelector];     }     return signature;}- (void)wt_forwardInvocation:(NSInvocation *)anInvocation{    if (strcmp(anInvocation.methodSignature.methodReturnType, "@") == 0)    {          anInvocation.selector = @selector(wt_nil);         [anInvocation invokeWithTarget:self];         return;    }    for (NSObject *object in NSNullObjects)    {          if ([object respondsToSelector:anInvocation.selector])          {                [anInvocation invokeWithTarget:object];                return;          }    }     [self wt_forwardInvocation:anInvocation];    //  [self doesNotRecognizeSelector:aSelector];}- (id)wt_nil{     return nil;}+ (void)wt_swizzleInstanceMethodWithClass:(Class)clazz originalSel:(SEL)original replacementSel:(SEL)replacement{      Method originMethod = class_getInstanceMethod(clazz, original);      Method replaceMethod = class_getInstanceMethod(clazz, replacement);      if (class_addMethod(clazz, original, method_getImplementation(replaceMethod), method_getTypeEncoding(replaceMethod))      {             class_replaceMethod(clazz, replacement, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));      }      else      {            method_exchangeImplementations(originMethod, replaceMethod);      }}@end

测试代码就不加了。


0 0