setValue和setObject,NSDictionary安全赋值

傻逼的惊醒

钟情于追求高大上的技术,精简快的编程,却忽略了好用且安全的系统方法,那就是我在寻求利用runtime方法实现NSDictionary和NSMutableDictionary安全使用的时候,发现了系统NSMutableDictionary一个好东西

1、setValue和setObject的区别

    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    NSMutableArray *array = [NSMutableArray array];
    [array insertObject:@"1" atIndex:0];
    [array insertObject:@"2" atIndex:1];
    
    [dic setObject:[NSNull null] forKey:@"haha"];
    [dic setObject:[NSNull null] forKey:array];
    [dic setObject:[NSNull null] forKey:[NSNull null]];
    [dic setObject:@1 forKey:@""];
    [dic setObject:@"" forKey:@1];
    [dic setObject:nil forKey:@""];
    [dic setObject:@"" forKey:nil];
    NSLog(@"dic:%@",dic);
    //setobject中的key和value可以为除了nil外的任何对象
    NSLog(@"*****************");
    
    [dic removeAllObjects];
    NSLog(@"dic:%@",dic);
    
    [dic setValue:[NSNull null] forKey:@"haha"];
    [dic setValue:[NSNull null] forKey:array];
    [dic setValue:[NSNull null] forKey:[NSNull null]];
    [dic setValue:@1 forKey:@""];
    [dic setValue:@"" forKey:@1];
    [dic setValue:nil forKey:@""];
    [dic setValue:@"" forKey:nil];
    [dic setValue:@"" forKey:@"hehe"];
    [dic setValue:array forKey:@""];
    NSLog(@"dic2:%@",dic);
    //setValue中的KEY只能为字符串 value可以为nil也可以为空对象[NSNull null]
    

2、重点是setValue的value可以为nil,也可以为空对象[NSNull null]

3、开发中设置请求参数,传递数据等使用NSDictionay的时候尽量使用setValue是不是就能避免部分崩溃问题。

4、对于利用runtime实现NSDictionary和NSMutableDictionary的安全,代码如下(开发的时候还是要暴露问题的,所以设置生产环境生效):

@implementation NSObject (Swizzling)
#ifdef DEBUG
#else
+ (BOOL)gl_swizzleMethod:(SEL)origSel withMethod:(SEL)altSel {
    Method origMethod = class_getInstanceMethod(self, origSel);
    Method altMethod = class_getInstanceMethod(self, altSel);
    if (!origMethod || !altMethod) {
        return NO;
    }
    class_addMethod(self,
                    origSel,
                    class_getMethodImplementation(self, origSel),
                    method_getTypeEncoding(origMethod));
    class_addMethod(self,
                    altSel,
                    class_getMethodImplementation(self, altSel),
                    method_getTypeEncoding(altMethod));
    method_exchangeImplementations(class_getInstanceMethod(self, origSel),
                                   class_getInstanceMethod(self, altSel));
    return YES;
}

+ (BOOL)gl_swizzleClassMethod:(SEL)origSel withMethod:(SEL)altSel {
    return [object_getClass((id)self) gl_swizzleMethod:origSel withMethod:altSel];
}

#endif
@end


@implementation NSDictionary (NilSafe)
#ifdef DEBUG
#else
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self gl_swizzleMethod:@selector(initWithObjects:forKeys:count:) withMethod:@selector(gl_initWithObjects:forKeys:count:)];
        [self gl_swizzleClassMethod:@selector(dictionaryWithObjects:forKeys:count:) withMethod:@selector(gl_dictionaryWithObjects:forKeys:count:)];
    });
}

+ (instancetype)gl_dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(NSUInteger)cnt {
    id safeObjects[cnt];
    id safeKeys[cnt];
    NSUInteger j = 0;
    for (NSUInteger i = 0; i < cnt; i++) {
        id key = keys[i];
        id obj = objects[i];
        if (!key || !obj) {
            continue;
        }
        safeKeys[j] = key;
        safeObjects[j] = obj;
        j++;
    }
    return [self gl_dictionaryWithObjects:safeObjects forKeys:safeKeys count:j];
}

- (instancetype)gl_initWithObjects:(const id [])objects forKeys:(const id [])keys count:(NSUInteger)cnt {
    id safeObjects[cnt];
    id safeKeys[cnt];
    NSUInteger j = 0;
    for (NSUInteger i = 0; i < cnt; i++) {
        id key = keys[i];
        id obj = objects[i];
        if (!key || !obj) {
            continue;
        }
        if (!obj) {
            obj = [NSNull null];
        }
        safeKeys[j] = key;
        safeObjects[j] = obj;
        j++;
    }
    return [self gl_initWithObjects:safeObjects forKeys:safeKeys count:j];
}
#endif

@end


@implementation NSMutableDictionary (NilSafe)

#ifdef DEBUG
#else
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class1 = NSClassFromString(@"__NSDictionaryM");
        [class1 gl_swizzleMethod:@selector(setObject:forKey:) withMethod:@selector(gl_setObject:forKey:)];
        [class1 gl_swizzleMethod:@selector(setObject:forKeyedSubscript:) withMethod:@selector(gl_setObject:forKeyedSubscript:)];
    });
}

- (void)gl_setObject:(id)anObject forKey:(id)aKey {
    if (!aKey || !anObject) {
        return;
    }
    [self gl_setObject:anObject forKey:aKey];
}

- (void)gl_setObject:(id)obj forKeyedSubscript:(id)key {
    if (!key || !obj) {
        return;
    }
    [self gl_setObject:obj forKeyedSubscript:key];
}
#endif

@end

你可能感兴趣的:(setValue和setObject,NSDictionary安全赋值)