ios 针对数组越界的崩溃优化

数组越界是常见的崩溃 , 崩溃日记是类似这样的 :

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 22 beyond bounds for empty NSArray'

网上也找过怎么解决,但是都不是太彻底, 由于 NSArray是一个类簇,需要把所有的入口都封住才算完美 . 方法还是很常见的,用了runtime的方法替换 . 然后 给NSArray加类别 , 部分核心代码:


@implementation NSArray (SafeIndex)

+ (void)load{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        // NSArray 是一个类簇,具体有三个子类__NSArray0,__NSSingleObjectArrayI,__NSArrayI,

        // 还有一个__NSPlaceholderArray是占位的,不实际使用
        // 对__NSArray0,__NSSingleObjectArrayI来说,下面三种调用的同一个方法objectAtIndex

        /** 对__NSArrayI,__NSArrayM来说,objectAtIndex 和 objectAtIndexedSubscript 有不同的实现,

         array[22]调用了objectAtIndexedSubscript */

        //        [array objectAtIndex:22];

        //        [array objectAtIndexedSubscript:22];

        //        array[22];

        [objc_getClass("__NSArray0") gl_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(emptyObjectIndex:)];

        [objc_getClass("__NSSingleObjectArrayI") gl_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(singleObjectIndex:)];

        [objc_getClass("__NSArrayI") gl_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(safe_arrObjectIndex:)];

        [objc_getClass("__NSArrayI") gl_swizzleMethod:@selector(objectAtIndexedSubscript:) withMethod:@selector(safe_objectAtIndexedSubscript:)];

        
        [objc_getClass("__NSArrayM") gl_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(safeObjectIndex:)];

        [objc_getClass("__NSArrayM") gl_swizzleMethod:@selector(objectAtIndexedSubscript:) withMethod:@selector(mutableArray_safe_objectAtIndexedSubscript:)];

        [objc_getClass("__NSArrayM") gl_swizzleMethod:@selector(insertObject:atIndex:) withMethod:@selector(safeInsertObject:atIndex:)];

        [objc_getClass("__NSArrayM") gl_swizzleMethod:@selector(addObject:) withMethod:@selector(safeAddObject:)];


    });

}

- (id)emptyObjectIndex:(NSInteger)index {

    NSLog(@"__NSArray0 取一个空数组 objectAtIndex , 崩溃") ;

    return nil;

}

- (id)singleObjectIndex:(NSInteger)index {

    if (index >= self.count || index < 0) {

        NSLog(@"__NSSingleObjectArrayI 取一个不可变单元素数组时越界 objectAtIndex , 崩溃") ;

        return nil;

    }

    return [self singleObjectIndex:index];

}

- (id)safe_arrObjectIndex:(NSInteger)index{

    if (index >= self.count || index < 0) {

        NSLog(@"__NSArrayI 取不可变数组时越界 objectAtIndex , 崩溃") ;

        return nil;

    }

    return [self safe_arrObjectIndex:index];
}

- (id)safe_objectAtIndexedSubscript:(NSInteger)index{

    if (index >= self.count || index < 0) {

        NSLog(@"__NSArrayI 取不可变数组时越界 objectAtIndexedSubscript , 崩溃") ;

        return nil;

    }

    return [self safe_objectAtIndexedSubscript:index];
}

- (id)mutableArray_safe_objectAtIndexedSubscript:(NSInteger)index{

    if (index >= self.count || index < 0) {

        NSLog(@"__NSArrayM 取可变数组时越界 objectAtIndexedSubscript , 崩溃") ;

        return nil;

    }

    return [self mutableArray_safe_objectAtIndexedSubscript:index];
}

- (id)safeObjectIndex:(NSInteger)index{

    if (index >= self.count || index < 0) {

        NSLog(@"__NSArrayM 取可变数组时越界 objectAtIndex , 崩溃") ;

        return nil;

    }

    return [self safeObjectIndex:index];

}

- (void)safeInsertObject:(id)object atIndex:(NSUInteger)index{

    if (index>self.count) {

        NSLog(@"__NSArrayM 添加元素越界 insertObject:atIndex: , 崩溃") ;

        return ;

    }

    if (object == nil) {

        NSLog(@"__NSArrayM 添加空元素 insertObject:atIndex: , 崩溃") ;

        return ;

    }

    [self safeInsertObject:object atIndex:index];

}

- (void)safeAddObject:(id)object {

    if (object == nil) {

        NSLog(@"__NSArrayM 添加空元素 addObject , 崩溃") ;

        return ;

    }
    [self safeAddObject:object];

}

@end



下载地址: https://download.csdn.net/download/u014600626/10400062 

或者 cocoa上的 : http://code.cocoachina.com/view/137085

猜你喜欢

转载自blog.csdn.net/u014600626/article/details/80238422