Yesterday, I saw a problem from a friend in the group and took over a historical bug of an existing project: Project has been completed, the amount of code is very big, there are a lot of custom model classes, and there are many nested model class directly, before all about the number of the server returns a model class are unified with nsstrings storage, return but the background is not a string, led to turn YYModel dictionary model, all of the string model is like this:

NSDictionary *dict = @{
                       @"fee"@ : [NSNumber numberWithDouble: 807.69]"firend": @ {@"fee": [NSNumber numberWithDouble:807.69]}}; // Similar model class @interface Person: nsobject@property (nonatomic, strong) NSString *fee; @property(nonatomic, strong) Person *friend; @end YYModel The string after the dictionary is converted to the model: p.friend.fee = @"807.6900000000001"
Copy the code

Modify up to the situation of the trouble is that the background there are a lot of different field name of data is returned, and the model set model, the model set array of these cases, whether the client to change the type of model classes, or change the background, is a very big workload, need to change the project much more special place, change and need to test in turn, is very time consuming.

In the end, I still came up with the most convenient way. I don’t need to change any code of the project. I just need to create a classification file, exchange it with the Runtime method, and convert the NSNumber type of the dictionary into NSString without loss of accuracy before YYModel assigns data to the model through the dictionary. Re-pass YYModel the original method on the line.

Simply add the following classification file to your project to solve this problem. This background does not need the code, the client does not need to change any code, to achieve zero intrusion of the project source code.

Source:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSObject (ModelExchange)

@end

NS_ASSUME_NONNULL_END
Copy the code
#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
Copy the code