眾所周知,服務器返回的數據時不時的就不靠譜一下,返回NSNull類型引起客戶端crash,這種定時炸彈我們如果通過:
[des isKindOfClass:[NSNull class]]
這樣判斷只能解決某個問題,然而對于不確定的返回null無法下手,另外到處寫這種代碼看起來也是很不爽。
解決:利用消息轉發
消息轉發不了解的可以自行百度
在寫的時候,我們要考慮@"",@0,@{},@[]這幾種常用的類型空值, NSNull實例在調用到一些不屬于它的方法的時候, 如果@"",@0,@{},@[]可以響應的時候就丟給他們去處理去。
比如 調用 intvalue,可以丟給@0去處理。
詳細代碼說明
#import "NSNull+safe.h"
#define NullObjects @[@"",@0,@{},@[]]
@implementation NSNull (safe)
//必須返回一個方法簽名不能為空
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
NSMethodSignature *signature = [super methodSignatureForSelector:selector];
if (signature != nil) return signature;
for (NSObject *object in NullObjects) {
signature = [object methodSignatureForSelector:selector];
if (signature) {
//strcmp比較兩個字符串,相同返回0
//這里 @ 是指返回值為對象 id
if (strcmp(signature.methodReturnType, "@") == 0) {
signature = [[NSNull null] methodSignatureForSelector:@selector(__returnNil)];
}
break;
}
}
return signature;
}
//消息轉發的最后一步
- (void)forwardInvocation:(NSInvocation *)anInvocation {
//如果返回值是對象 設置方法為__returnNil
if (strcmp(anInvocation.methodSignature.methodReturnType, "@") == 0) {
anInvocation.selector = @selector(__returnNil);
[anInvocation invokeWithTarget:self];
return;
}
//遍歷 查看 @"",@0,@{},@[] 那個響應了selector,然后丟給它去執行
for (NSObject *object in NullObjects) {
if ([object respondsToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:object];
return;
}
}
//拋出異常
[self doesNotRecognizeSelector:anInvocation.selector];
}
- (id)__returnNil {
return nil;
}
@end
demo地址
歡迎star