不改项目代码解决YYModel数字转字符串的精度问题

昨天看到一个群里的朋友的问题,接手一个已有项目的历史遗留bug:项目已经完成,代码量很大,有不少自定义模型类,而且模型类直接存在各类嵌套,以前的模型类全部关于服务器返回的数字都是统一用NSString存储的,可是后台返回的并非字符串,致使了YYModel字典转模型的时候,全部模型的字符串都是这样:数组

NSDictionary *dict = @{
                       @"fee": [NSNumber numberWithDouble:807.69],
                       @"firend":@{
                               @"fee": [NSNumber numberWithDouble:807.69]
                               }
                       };

后台返回的数字:807.69

// 相似的模型类
@interface Person : NSObject
@property(nonatomic, strong) NSString *fee;
@property(nonatomic, strong) Person *friend;
@end

YYModel字典转模型后的字符串:p.friend.fee = @"807.6900000000001"
复制代码

修改起来麻烦的状况在于:后台有大量的不一样字段名的数据都是这样返回的,并且存在模型套模型、模型套模型数组这些状况,不管是客户端改模型类的类型,仍是后台改,都是一个很大的工做量,须要改项目中特别多的地方,改起来又须要从新依次测试,很是的耗时间。bash

最后我仍是想到了一个最取巧的办法,不须要去改动项目的任何代码,只须要建立一个分类文件,用runtime方法交换,在YYModel经过字典给模型赋值数据的方法以前,先将字典的NSNumber类型转成不损失精度的NSString,在尾部去0,从新传给YYModel原来的方法就好了。服务器

只须要将下面这个分类文件添加到项目中,就能够解决这个问题。这样后台不须要该代码,客户端也不须要改任何代码,实现了对项目源代码的0入侵。测试

源码:ui

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSObject (ModelExchange)

@end

NS_ASSUME_NONNULL_END
复制代码
#import "NSObject+ModelExchange.h"
#import "NSObject+YYModel.h"
#import <objc/runtime.h>

@implementation NSObject (ModelExchange)

+ (void)load {
    Method method1 = class_getInstanceMethod([self class], @selector(yy_modelSetWithDictionary:));
    Method method2 = class_getInstanceMethod([self class], @selector(my_modelSetWithDictionary:));
    method_exchangeImplementations(method1, method2);
}

- (BOOL)my_modelSetWithDictionary:(NSDictionary *)dic {
    NSMutableDictionary *mDictionary = [NSMutableDictionary dictionary];
    [dic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[NSNumber class]]) {
            NSNumber *num = (NSNumber *)obj;
            NSNumberFormatter *formatter = [NSNumberFormatter new];
            formatter.numberStyle = NSNumberFormatterDecimalStyle;
            [formatter setGroupingSeparator:@""];
            NSString *str = [formatter stringFromNumber:num];
            [mDictionary setValue:str forKey:key];
        } else {
            [mDictionary setValue:obj forKey:key];
        }
    }];
    return [self my_modelSetWithDictionary:mDictionary];
}

@end
复制代码
相关文章
相关标签/搜索