iOS消息转发 – 解决NSNull取值崩溃
运用场景
如果数据接口返回的有data中的age是null, 此时取值data[@"age”]会崩溃; 崩溃信息显示:-[NSNull objectForKeyedSubscript:]: unrecognized selector sent to instance 0x104d0bea8
;
利用if(data[@"age”])
{ 取值 }, 也可以避免崩溃, 但是老是这样写造成大量重复代码, 这时我们只要利用消息转发机制就完全可以避免崩溃, 具体请看下面的示例
# 首先创建一个NSNull分类 NSNull (safeNull)
引入#import <objc/message.h>
实现以下两个方法
获取方法签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
标准转发
- (void)forwardInvocation:(NSInvocation *)anInvocation
//
// NSNull+safeNull.m
// MessageForward
//
// Created by 聂银龙 on 2019/8/6.
// Copyright © 2019 聂银龙. All rights reserved.
//
#import "NSNull+safeNull.h"
#import <objc/message.h>
#define NSNullObjectsArr @[@"", @0, @{}, @[]]
@implementation NSNull (safeNull)
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
for (NSObject *obj in NSNullObjectsArr) {
signature = [obj methodSignatureForSelector:aSelector];
if (signature) {
break;
}
}
}
return signature;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
for (NSObject *objc in NSNullObjectsArr) {
if ([objc respondsToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:objc];
return;
}
}
}
@end
实际使用
/
// ViewController.m
// MessageForward
//
// Created by 聂银龙 on 2019/8/6.
// Copyright © 2019 聂银龙. All rights reserved.
//
#import "ViewController.h"
#import "NSNull+safeNull.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
id dic = [NSNull null];
NSLog(@"%@", dic[@"age"]); // 利用消息转发, 从而不会崩溃
}
@end