Latest 0.2.0
Homepage https://github.com/FCXPods/FCXSafeCollections
License MIT
Authors

支持使用pod:(pod ‘FCXSafeCollections’, ‘~> 0.2.0’)

解决NSArray、NSMutableArray、NSDictionary、NSMutableDictionary引起的闪退

使用了MethodSwizzle解决项目中经常遇到的数组越界、字典键值对为空操作等闪退问题,
在Debug模式会在控制台输出相应的错误原因,并且不会导致程序闪退

+ (void)load {

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        //        NSArray
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayI") originalSelector:@selector(objectAtIndex:) swizzledMethod:@selector(fcx_safeObjectAtIndex:)];

        //        NSMutableArray
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSelector:@selector(objectAtIndex:) swizzledMethod:@selector(fcx_safeObjectAtIndex:)];
        //        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSelector:@selector(addObject:) swizzledMethod:@selector(fcx_safeAddObject:)];
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSelector:@selector(replaceObjectAtIndex:withObject:) swizzledMethod:@selector(fcx_safeReplaceObjectAtIndex:withObject:)];
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSelector:@selector(insertObject:atIndex:) swizzledMethod:@selector(fcx_safeInsertObject:atIndex:)];

        //        NSDictionary
        //        [self swizzleClassMethodWithClass:[NSDictionary class] originalSelector:@selector(dictionaryWithObjects:forKeys:count:) swizzledMethod:@selector(fcx_safeDictionaryWithObjects:forKeys:count:)];

        //        NSMutableDictionary
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSDictionaryM") originalSelector:@selector(setObject:forKey:) swizzledMethod:@selector(fcx_safeSetObject:forKey:)];

    });
}

- (void)testSafe {
    //Array
    NSArray *array  = @[@1, @2];

    NSLog(@"index==== %@", array[2]);

    NSMutableArray *muArray = [[NSMutableArray alloc] initWithObjects:@"1", nil];
    NSLog(@"****");
    NSLog(@"=======muarray %@", muArray[2]);

    [muArray replaceObjectAtIndex:3 withObject:@""];
    [muArray replaceObjectAtIndex:0 withObject:nil];
    [muArray insertObject:@2 atIndex:2];

    //Dict
    NSMutableDictionary *muDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"obj", @"key", nil];

    [muDict setObject:nil forKey:@"1"];
    [muDict setObject:@"1" forKey:nil];
}

解决KeyValue引起的程序闪退

//当对一个非类对象属性设置nil时,就会执行setNilValueForKey:方法,setNilValueForKey:方法的默认实现,是产生一个NSInvalidArgumentException的异常,但是你可以重写这个方法.
- (void)setNilValueForKey:(NSString *)key {

    FCXSCLOG(@"[%@ %@]: could not set nil as the value for the key %@.", NSStringFromClass([self class]), NSStringFromSelector(_cmd), key);
}

//如果没有对应的访问器方法(setter方法),如果接受者的类的+accessInstanceVariablesDirectly方法返回YES,那么就查找这个接受者的与key相匹配的实例变量(匹配模式为_<key>,_is<Key>,<key>,is<Key>):比如:key为age,只要属性存在_age,_isAge,age,isAge中的其中一个就认为匹配上了,如果找到这样的一个实例变量,并且的类型是一个对象指针类型,首先released对象上的旧值,然后把传入的新值retain后的传入的值赋值该成员变量,如果方法的参数类型是NSNumber或NSValue的对应的基本类型,先把它转换为基本数据类,再执行方法,传入转换后的数据.
//+ (BOOL)accessInstanceVariablesDirectly {
//    return YES;
//}

//对于数据模型中缺少的、不能与任何键配对的属性的时候,系统会自动调用setValue:forUndefinedKey:这个方法,该方法默认的实现会引发一个NSUndefinedKeyExceptiony异常,但是我们可以重写setValue:forUndefinedKey:方法让程序在运行过程中不引发任何异常信息且正常工作
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {

    FCXSCLOG(@"[%@ %@]: this class is not key value coding-compliant for the key %@.", NSStringFromClass([self class]), NSStringFromSelector(_cmd), key);
}

//通过valueForKey获取对象属性值的方法时,如果代码中的key值不存在,系统会自动调用valueForUndefinedKey:这个方法,该方法默认的实现会引发一个NSUndefinedKeyExceptiony异常,但是我们可以重写valueForUndefinedKey:方法让程序在运行过程中不引发任何异常信息且正常工作
/**
 *  通过valueForKey获取对象属性值的方法时,如果代码中的key值不存在,系统会自动调用valueForUndefinedKey:这个方法,该方法默认的实现会引发一个NSUndefinedKeyExceptiony异常,但是我们可以重写valueForUndefinedKey:方法让程序在运行过程中不引发任何异常信息且正常工作
 *
 *  @return nil
 *
 *  @notice 虽然这步可以返回nil不闪退,但是后续操作依然可能有问题
 */
- (id)valueForUndefinedKey:(NSString *)key {

    FCXSCLOG(@"[%@ %@]: this class is not key value coding-compliant for the key %@.", NSStringFromClass([self class]), NSStringFromSelector(_cmd), key);
    return nil;
}

- (void)testKeyValue {

    Person *xiaoming = [[Person alloc] init];
    [xiaoming setValue:@"xiaoming" forKey:@"name"];
    NSLog(@"name %@", xiaoming.name);
    [xiaoming setValue:nil forKey:@"name"];
    [xiaoming setValue:nil forKey:@"array"];
    //    [xiaoming setValue:nil forKey:@"person1"];
    [xiaoming setValue:@"aa" forKey:@"age"];
    //    [xiaoming setValue:nil forKey:@"age"];
    //    [xiaoming setNilValueForKey:@"age"];
    NSLog(@"name %@ age %ld", xiaoming.name, xiaoming.age);

    //    [xiaoming setValue:@"xiaoming" forKey:@"person1"];
    [xiaoming valueForKey:@"person1"];
    [xiaoming valueForKey:@"age1"];
}

Latest podspec

{
    "name": "FCXSafeCollections",
    "version": "0.2.0",
    "summary": "u5de5u7a0bu5b89u5168u7c7buff0cu89e3u51b3u9879u76eeu4e2du7ecfu5e38u9047u5230u7684u6570u7ec4u8d8au754cu3001u5b57u5178u952eu503cu5bf9u4e3au7a7au64cdu4f5cu7b49u95eau9000u95eeu9898.",
    "description": "u89e3u51b3u9879u76eeu4e2du7ecfu5e38u9047u5230u7684u6570u7ec4u8d8au754cu3001u5b57u5178u952eu503cu5bf9u4e3au7a7au64cdu4f5cu7b49u95eau9000u95eeu9898u3001keyValueu5f15u8d77u7684u95eau9000uff0c u5728Debugu6a21u5f0fu4f1au5728u63a7u5236u53f0u8f93u51fau76f8u5e94u7684u9519u8befu539fu56e0uff0cu5e76u4e14u4e0du4f1au5bfcu81f4u7a0bu5e8fu95eau9000.",
    "homepage": "https://github.com/FCXPods/FCXSafeCollections",
    "license": "MIT",
    "authors": {
        "fengchuanxiang": "[email protected]"
    },
    "source": {
        "git": "https://github.com/FCXPods/FCXSafeCollections.git",
        "tag": "0.2.0"
    },
    "source_files": "FCXSafeCollections/"
}

Pin It on Pinterest

Share This