我就职过的公司,都出现过不止一次因为后台实际数据类型和文档不一致导致的程序线上崩溃问题。原则上即使服务器离线了,app都不应该直接闪退,所以app应当具有对服务器异常情况进行处理的能力。使用ValueX可以有效避免后台返回数据类型异常导致的程序崩溃。

异常场景

  • 场景1:NSString类型变成NSNull
  • 场景2:nil变成@"<null>"
  • 场景3:userId不确定是NSString还是NSNumber
  • 场景4:NSDictionary中嵌套的容器变成了json字符串格式

问题抽象

  • 实际类型与定义类型不符
  • 实际类型与期望类型不一致

设计接口

假如我得到一个值NSString *obj,实际上可能是NSNull,可能是NSNumber,可能是空数据的@"<null>"或者@"(null)"等各种表述。
那么我需要确保NSSafeString(obj)的结果一定是NSString类型的值,如果是空数据,就应该是nil。如果是@123这样的数字,那么应该得到@"123"这样的字符串。

如果是json数据,它可能以NSData类型存在,可能以Json字符串NSString类型存在,可能以NSArray或者NSDictionary对象形式存在。
我需要的是我需要什么类型就能直接get到。
例如ValueX(obj).stringValue就得到这个数据的Json字符串,ValueX(obj).dictionaryValue就得到这个数据的字典对象。

所以这个库就分为两部份工作,一部分是将实际类型与定义类型一致化;第二部分是将已知类型转换成它能够转换的其他类型。

类型安全

针对OC中常用的6种数据类型NSString/NSNumber/NSData/NSArray/NSSet/NSDictionary一一进行判断,写出6个函数:

1
2
3
4
5
6
FOUNDATION_EXTERN NSString * __nullable NSSafeString(id obj);
FOUNDATION_EXTERN NSNumber * __nullable NSSafeNumber(id obj);
FOUNDATION_EXTERN NSData * __nullable NSSafeData(id obj);
FOUNDATION_EXTERN NSArray * __nullable NSSafeArray(id obj);
FOUNDATION_EXTERN NSSet * __nullable NSSafeSet(id obj);
FOUNDATION_EXTERN NSDictionary * __nullable NSSafeDictionary(id obj);

确保从这些函数出来的值是与定义类型一致的值。

类型转换

即使拿到的值与定义类型一致,有时候我们要用的可能又是其他类型。

1
FOUNDATION_EXTERN VXObject *ValueX(id <VXConvertable>obj);

确保VXObject类型可以通过点语法直接得到原数据所能够转换的其他类型。VXObject是一种中间类型,针对上述6种数据类型,每一种可以转换成其他哪些类型进行一一判断。

其中,NSNumber只可以转换为NSString,以及NSData。标记为VXConvertable。
表示数字的NSString,可以转换成NSNumber,表示json的字符串可以转换成对应的NSArray或者NSDictionary,标记为VXConvertableData。
反过来NSArray/NSSet或者NSDictionary则标记为VXConvertableObject。

1
2
3
4
5
6
7
8
9
10
11
12
@interface NSString (VXObject) <VXConvertableData>
@end
@interface NSNumber (VXObject) <VXConvertable>
@end
@interface NSData (VXObject) <VXConvertableData>
@end
@interface NSArray (VXObject) <VXConvertableObject>
@end
@interface NSSet (VCObject) <VXConvertableObject>
@end
@interface NSDictionary (VXObject) <VXConvertableObject>
@end

它们的协议内容是:

1
2
3
4
5
6
7
8
9
10
11
@protocol VXConvertable <NSObject>
- (VXObject *)vx;
@end

@protocol VXConvertableObject <VXConvertable>
- (VXObject *)vxWithOptions:(NSJSONWritingOptions)opt;
@end

@protocol VXConvertableData <VXConvertable>
- (VXObject *)vxWithOptions:(NSJSONReadingOptions)opt;
@end

就按照这个思路进行开发,实现的代码就不再赘述了,文档和源码链接都在文末。

文档链接

https://xaoxuu.com/wiki/valuex/

源码链接

https://github.com/xaoxuu/ValueX/


 评论