不改項目代碼解決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
複製代碼
相關文章
相關標籤/搜索