起因:做网络交互时,经常会使用JSON作为数据的承载体,本来是件好事,但是用多了,发现iOS侧偶尔会出现异常,几经比较发现是服务器给的数据有问题,该给INT的给按照STR给了,
服务器能做动态更新,可客户端不行啊,怎么办?NSDictionary读到的是id类型,如果是数字,需要再转换下才可以,出问题就在这里.那解决思路就在这里,在这里增加判断
实现
用到了以下几个知识点
@encode()
为了更好的互操作性,Objective-C 的数据类型,甚至自定义类型、函数或方法的元类型,都可以使用 ASCII 编码。@encode(aType) 可以返回该类型的 C 字符串(char *)的表示

[obj objcType]
获取obj对象的对象类型的C编码字符串.

OK,比较就好.

 

#import <Foundation/Foundation.h>
/*
 改造
 1 增加读取数据时,如果没有键值,返回默认值的动作.
 2 屏蔽无键值时字典异常的问题.
 3 增加双字段类型CGPoint的读取动作.
 4 增加底层判断实际数据类型与读取动作不匹配导致的问题.
 */

@interface NSDictionary (ReadAdditions)

- (BOOL)getBoolValueForKey:(NSString *)key defaultValue:(BOOL)defaultValue;
- (NSInteger)getIntValueForKey:(NSString *)key defaultValue:(NSInteger)defaultValue;
- (float)getFloatValueForKey:(NSString *)key defaultValue:(float)defaultValue;
- (time_t)getTimeValueForKey:(NSString *)key defaultValue:(time_t)defaultValue;
- (long long)getLongLongValueValueForKey:(NSString *)key defaultValue:(long long)defaultValue;
- (NSString *)getStringValueForKey:(NSString *)key defaultValue:(NSString *)defaultValue;
- (id)getValueForKey:(NSString*)key defaultValue:(id)defalueValue;
- (CGPoint)getPointForKey:(NSString*)xKey yKey:(NSString*)yKey defaultValue:(CGPoint)defaultValue;
@end

 实现

#import "NSDictionaryReadAdditions.h"

typedef NS_ENUM(NSUInteger, PODTYPE)
{
    PT_UNKNOWN = -1,
    PT_INT = 0,
    PT_FLOAT,
    PT_DOUBLE,
    PT_BOOL,
    PT_INT64,
    PT_STRING,
    PT_ARRAY,
};

@implementation NSDictionary (ReadAdditions)

-(PODTYPE)getPodType:(id)obj
{
    if([obj isKindOfClass:[NSNumber class]])
    {
        const char * pObjCType = [((NSNumber*)obj) objCType];
        if (strcmp(pObjCType, @encode(BOOL)) == 0)
        {
            return PT_BOOL;
        }
        if (strcmp(pObjCType, @encode(int)) == 0)
        {
            return PT_INT;
        }
        if (strcmp(pObjCType, @encode(float)) == 0)
        {
            return PT_FLOAT;
        }
        if (strcmp(pObjCType, @encode(double)) == 0)
        {
            return PT_DOUBLE;
        }
    }
    return PT_UNKNOWN;
}
-(BOOL)isPodIntObj:(id)obj
{
    if (nil == obj)
        return NO;
    if([obj isKindOfClass:[NSNumber class]])
    {
        const char * pObjCType = [((NSNumber*)obj) objCType];
        if (strcmp(pObjCType, @encode(int)) == 0)
        {
            return YES;
        }
    }
    return NO;
}
-(BOOL)isPodBoolObj:(id)obj
{
    if (nil == obj)
        return NO;
    if([obj isKindOfClass:[NSNumber class]])
    {
        const char * pObjCType = [((NSNumber*)obj) objCType];
        if (strcmp(pObjCType, @encode(BOOL)) == 0)
        {
            return YES;
        }
    }
    return NO;
}
-(BOOL)isPodFloatObj:(id)obj
{
    if (nil == obj)
        return NO;
    if([obj isKindOfClass:[NSNumber class]])
    {
        const char * pObjCType = [((NSNumber*)obj) objCType];
        if (strcmp(pObjCType, @encode(float)) == 0)
        {
            return YES;
        }
    }
    return NO;
}
-(BOOL)isPodInt64Obj:(id)obj
{
    if (nil == obj)
        return NO;
    if([obj isKindOfClass:[NSNumber class]])
    {
        const char * pObjCType = [((NSNumber*)obj) objCType];
        if (strcmp(pObjCType, @encode(long long)) == 0)
        {
            return YES;
        }
    }
    return NO;
}
-(BOOL)isNSTypeObj:(id)obj andType:(Class)objClass
{
    if (nil == obj || nil == objClass)
        return NO;
    if ([obj isMemberOfClass:objClass])
    {
        return YES;
    }
    return NO;
}

- (BOOL)getBoolValueForKey:(NSString *)key defaultValue:(BOOL)defaultValue {
    id obj = [self getValueForKey:key defaultValue:nil];
    if (nil == obj)
    {
        return defaultValue;
    }
    if ([self isPodBoolObj:obj])
        return [obj boolValue];
    else
    {
        NSLog(@"警告[%s],数据对象类型不符:%@",__FUNCTION__, key);
    }
    return defaultValue;
}

- (NSInteger)getIntValueForKey:(NSString *)key defaultValue:(NSInteger)defaultValue {
    id obj = [self getValueForKey:key defaultValue:nil];
    if (nil == obj)
    {
        return defaultValue;
    }
    if ([self isPodIntObj:obj])
        return [obj integerValue];
    else
    {
        NSLog(@"警告[%s],数据对象类型不符:%@",__FUNCTION__, key);
    }
    return defaultValue;
}
- (float)getFloatValueForKey:(NSString *)key defaultValue:(float)defaultValue
{
    id obj = [self getValueForKey:key defaultValue:nil];
    if (nil == obj)
    {
        return defaultValue;
    }
    if ([self isPodFloatObj:obj])
        return [obj floatValue];
    else
    {
        NSLog(@"警告[%s],数据对象类型不符:%@",__FUNCTION__, key);
    }
    return defaultValue;
}

- (time_t)getTimeValueForKey:(NSString *)key defaultValue:(time_t)defaultValue {
	NSString *stringTime   = [self objectForKey:key];
    if ((id)stringTime == [NSNull null]) {
        stringTime = @"";
    }
	struct tm created;
    time_t now;
    time(&now);
    
	if (stringTime) {
		if (strptime([stringTime UTF8String], "%a %b %d %H:%M:%S %z %Y", &created) == NULL) {
			strptime([stringTime UTF8String], "%a, %d %b %Y %H:%M:%S %z", &created);
		}
		return mktime(&created);
	}
	return defaultValue;
}

- (long long)getLongLongValueValueForKey:(NSString *)key defaultValue:(long long)defaultValue {
    id obj = [self getValueForKey:key defaultValue:nil];
    if (nil == obj)
    {
        return defaultValue;
    }
    if ([self isPodInt64Obj:obj])
        return [obj longLongValue];
    else
    {
        NSLog(@"警告[%s],数据对象类型不符:%@",__FUNCTION__, key);
    }
    return defaultValue;
}

- (NSString *)getStringValueForKey:(NSString *)key defaultValue:(NSString *)defaultValue
{
    id obj = [self getValueForKey:key defaultValue:nil];
    if (nil == obj)
    {
        return defaultValue;
    }
    if ([self isNSTypeObj:obj andType:[NSString class]])
        return obj;
    else
    {
        NSLog(@"警告[%s],数据对象类型不符:%@",__FUNCTION__, key);
    }
    return defaultValue;
    
	return [self objectForKey:key] == nil || [self objectForKey:key] == [NSNull null] ? defaultValue : [self objectForKey:key];
}

-(id)getValueForKey:(NSString*)key defaultValue:(id)defaultValue
{
    return [self objectForKey:key] == nil || [self objectForKey:key] == [NSNull null]
    ? defaultValue : [self objectForKey:key];
}
-(CGPoint)getPointForKey:(NSString*)xKey yKey:(NSString*)yKey  defaultValue:(CGPoint)defaultValue
{
    CGPoint tmp = CGPointZero;
    tmp.x = [self getFloatValueForKey:xKey defaultValue:defaultValue.x];
    tmp.y = [self getFloatValueForKey:yKey defaultValue:defaultValue.y];
    return tmp;
}
@end