一行代码解决:服务器返回null导致应用崩溃
来源:互联网 发布:通关宝典 软件 编辑:程序博客网 时间:2024/05/17 00:08
背景1:是否有这样一种感受,你的应用会崩溃,查看崩溃日志或者调试发现后台返回的数据字段里面有null,这个null居然还是导致应用崩溃的“元凶”。
背景2:服务器返回的字段名和不一致,如果model属性少,你可以一个个对应赋值,多了肯定都会想到用运行时机制来赋值:
[selfsetValue:temDic[key]forKeyPath:key],这时候需要对两个地方的字段做映射。
思路:1、先判断是否需要映射 2、把服务器返回的数据赋给model 3、model属性null检查(不同类型赋不同值,并不是把所有null都赋@"")4、这个写法应该适应所有自定义的类型,所有给NSObject 加一个Category。
#import"NSObject+runtime.h"
@implementation NSObject (runtime)
- (void)fetchValueFormNetDict:(NSDictionary *)dic andMapDic:(NSDictionary *)MapDic{
NSArray *properties = [selfgetAllProperties];
//需要映射
if (MapDic !=nil) {
NSArray *allKeys = dic.allKeys;
NSMutableDictionary *temDic = [NSMutableDictionarydictionaryWithCapacity:allKeys.count];
for (int i = 0; i < allKeys.count; i ++) {
NSString *key = allKeys[i];
[temDicsetObject:dic[key]forKey:MapDic[key]];
}
//遍历属性数组
for (NSString *key in properties) {
//判断字典中是否包含这个key
[selfsetValue:temDic[key]forKeyPath:key];
}
}
else//不需要映射
{
//遍历属性数组
for (NSString *key in properties) {
//判断字典中是否包含这个key
[selfsetValue:dic[key]forKeyPath:key];
}
}
//null或者 nil处理
[selfnullDeal];
}
//获取所有的属性名
- (NSArray *)getAllProperties
{
u_int count;
objc_property_t *properties =class_copyPropertyList([selfclass], &count);
NSMutableArray *propertiesArray = [NSMutableArrayarrayWithCapacity:count];
for (int i = 0; i<count; i++)
{
constchar* propertyName =property_getName(properties[i]);
[propertiesArrayaddObject: [NSStringstringWithUTF8String: propertyName]];
}
free(properties);
return propertiesArray;
}
-(void)nullDeal
{
//找到属性对应的类型
NSDictionary *typeDic = [selfclassPropsFor:[selfclass]];
NSArray *arr = typeDic.allKeys;//所有属性名字
for (int i = 0; i < arr.count; i++) {
//属性类型名字(字符串格式)
NSString *typeString = typeDic[arr[i]];
if ([[selfvalueForKey:arr[i]]isKindOfClass:[NSNullclass]] || [selfvalueForKey:arr[i]] ==nil) {
if ([typeStringisEqualToString:@"NSArray"]) {
[selfsetValue:@[]forKey:arr[i]];
}
if ([typeStringisEqualToString:@"NSString"]) {
[selfsetValue:@""forKey:arr[i]];
}
if ([typeStringisEqualToString:@"NSNumber"]) {
[selfsetValue:@0forKey:arr[i]];
}
if ([typeStringisEqualToString:@"NSDictionary"]) {
[selfsetValue:@{}forKey:arr[i]];
}
if ([typeStringisEqualToString:@"B"]) {
[selfsetValue:0forKey:arr[i]];
}
if ([typeStringisEqualToString:@"f"]) {
[selfsetValue:0forKey:arr[i]];
}
if ([typeStringisEqualToString:@"d"]) {
[selfsetValue:0forKey:arr[i]];
}
if ([typeStringisEqualToString:@"i"]) {
[selfsetValue:0forKey:arr[i]];
}
}
}
}
//获取属性名称数组
- (NSDictionary *)classPropsFor:(Class)klass
{
if (klass ==NULL) {
returnnil;
}
NSMutableDictionary *results = [[NSMutableDictionaryalloc]init];
unsignedint outCount, i;
objc_property_t *properties = class_copyPropertyList(klass, &outCount);
for (i =0; i < outCount; i++) {
objc_property_t property = properties[i];
constchar *propName =property_getName(property);
if(propName) {
constchar *propType =getPropertyType(property);
NSString *propertyName = [NSStringstringWithUTF8String:propName];
NSString *propertyType = [NSStringstringWithUTF8String:propType];
NSLog(@"propertyName %@ propertyType %@", propertyName, propertyType);
[resultssetObject:propertyTypeforKey:propertyName];
}
}
free(properties);
// returning a copy here to make sure the dictionary is immutable
return [NSDictionarydictionaryWithDictionary:results];
}
//获取属性类型的方法 c语言写法 T@"NSString",C,N,V_name Tf,N,V__float
staticconstchar *getPropertyType(objc_property_t property) {
constchar *attributes =property_getAttributes(property);
printf("attributes=%s\n", attributes);
char buffer[1 + strlen(attributes)];//多一个结束符号
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute =strsep(&state,",")) !=NULL) {
if (attribute[0] == 'T' && attribute[1] != '@') {
NSString *name = [[NSStringalloc]initWithBytes:attribute +1length:strlen(attribute) - 1encoding:NSASCIIStringEncoding];
return (constchar *)[namecStringUsingEncoding:NSASCIIStringEncoding];
}
elseif (attribute[0] == 'T' && attribute[1] == '@' &&strlen(attribute) ==2) {
// it's an ObjC id type:
return"id";
}
elseif (attribute[0] == 'T' && attribute[1] == '@') {
// it's another ObjC object type:
NSString *name = [[NSStringalloc]initWithBytes:attribute +3length:strlen(attribute) - 4encoding:NSASCIIStringEncoding];
return (constchar *)[namecStringUsingEncoding:NSASCIIStringEncoding];
}
}
return"";
}
@end
基本工作差不多完了,现在来自定义一个类型试试:
#import<Foundation/Foundation.h>
@interface UserModel :NSObject
@property(nonatomic,copy)NSString *name;
@property(nonatomic,copy)NSString *home;
@property(nonatomic,strong)NSNumber *old;
@property(nonatomic,strong)NSArray *arr;
@property(nonatomic,strong)NSDictionary *dic;
@property(nonatomic,assign)BOOL isBoll;
-(instancetype)initWithDic:(NSDictionary *)dic;
@end
#import"UserModel.h"
#import"NSObject+runtime.h"
@implementation UserModel
-(instancetype)initWithDic:(NSDictionary *)dic
{
if (self == [superinit]) {
// dic网络数据 mapDic 映射之后的字典
[selffetchValueFormNetDict:dicandMapDic:[selfmapDic]];
}
returnself;
}
////设置映射字典格式:@"网络数据字段名":@"model属性名"
//如果服务器返回的字段和 model的属性名字不一致则需要映射返回映射字典否则返回nil表示不需要映射
-(NSDictionary *)mapDic
{
return@{@"wzcName":@"name",@"wzcAddress":@"home",@"isbol":@"isBoll"};
}
@end
实列化一个UserModel对象
NSDictionary *data1 = @{@"wzcName":[NSNullnull],@"wzcAddress":@"杭州市西湖区",@"isbol":@1};
UserModel *model1 = [[UserModelalloc]initWithDic:data1];
结果如下:
这样在后面数据操作不会崩溃了。
- 一行代码解决:服务器返回null导致应用崩溃
- iOS中解决后台返回的null导致的崩溃问题
- 解决服务器返回错误数据格式导致Json解析出错造成app崩溃
- Spark优化-troubleshooting 解决算子函数返回NULL导致问题
- troubleshooting之解决算子函数返回NULL导致的问题
- 解决curl超时导致应用崩溃的问题
- 解决curl超时导致应用崩溃的问题
- 关于Fragment中的getActivity()返回null导致程序崩溃的解决方案
- 【已解决】onCreateViewHolder中的代码错误,导致程序崩溃
- Base64编码导致服务器崩溃
- 服务器返回null
- 服务器返回<null>处理
- 解决使用 model 时后台返回 null 或 nil 数据而造成的崩溃问题
- 解决mysql sum求和返回null问题或IFNULL应用
- iOS JSON返回的数据有NSNull导致程序崩溃及ios nil、NULL和NSNull的区别
- 解决后台杀应用,小米推送再次初始化导致ShareSDK初始化报错,使应用崩溃
- iOS项目中由于后台数据返回null导致的错误解决
- iOS项目中由于后台数据返回null导致的错误解决
- iOS学习-加速计和陀螺仪
- Codeforces Round #367 (Div. 2)E
- MYSQL优化实践
- Java多个线程之间处理共享数据的方式
- 欢迎使用CSDN-markdown编辑器
- 一行代码解决:服务器返回null导致应用崩溃
- AndroidStudio项目关联git远程仓库
- About the IMX6 PCIe Problem
- Webservice
- codeforces367(字符串hash求lcp比较大小,Trie解最大异或问题)
- 在使用ajax接收返回map的时候,提示406错误
- ios 对于UIView的动画的初步理解
- BZOJ3444 最后的晚餐
- 关于UPnP Device Architecture 2.0的阅读笔记(一)