iOS 防止数组越界导致崩溃之终极解决方法

5,232 阅读1分钟

防止数组越界,适用于下标索引 array[index] 和方法获取 [array objectAtIndex:index],如果越界返回 nil


NSArray+BeyondIntercept.h

#import <Foundation/Foundation.h>

@interface NSArray (BeyondIntercept)

@end

NSArray+BeyondIntercept.m

#import "NSArray+BeyondIntercept.h"
#import <objc/runtime.h>

@implementation NSArray (BeyondIntercept)

+ (void)load {
    Method oldObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:));
    Method newObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(newObjectAtIndex:));
    method_exchangeImplementations(oldObjectAtIndex, newObjectAtIndex);
    
    Method oldMutableObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndexedSubscript:));
    Method newMutableObjectAtIndex =  class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(newObjectAtIndexedSubscript:));
    method_exchangeImplementations(oldMutableObjectAtIndex, newMutableObjectAtIndex);
    
    Method oldMObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(objectAtIndex:));
    Method newMObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(newMutableObjectAtIndex:));
    method_exchangeImplementations(oldMObjectAtIndex, newMObjectAtIndex);
    
    Method oldMMutableObjectAtIndex = class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(objectAtIndexedSubscript:));
    Method newMMutableObjectAtIndex =  class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(newMutableObjectAtIndexedSubscript:));
    method_exchangeImplementations(oldMMutableObjectAtIndex, newMMutableObjectAtIndex);
}

- (id)newObjectAtIndex:(NSUInteger)index {
    @try {
        return [self newObjectAtIndex:index];
    } @catch (NSException * exception) {
        NSLog(@"Fatal: %@ %@", exception.name, exception.reason);
        return nil;
    }
}

- (id)newObjectAtIndexedSubscript:(NSUInteger)index {
    @try {
        return [self newObjectAtIndexedSubscript:index];
    } @catch (NSException *exception) {
        NSLog(@"Fatal: %@ %@", exception.name, exception.reason);
        return nil;
    }
}

- (id)newMutableObjectAtIndex:(NSUInteger)index {
    @try {
        return [self newMutableObjectAtIndex:index];
    } @catch (NSException *exception) {
        NSLog(@"Fatal: %@ %@", exception.name, exception.reason);
        return nil;
    }
}

- (id)newMutableObjectAtIndexedSubscript:(NSUInteger)index {
    @try {
        return [self newMutableObjectAtIndexedSubscript:index];
    } @catch (NSException *exception) {
        NSLog(@"Fatal: %@ %@", exception.name, exception.reason);
        return nil;
    }
}

@end

测试

NSArray *listAry = @[@1,@2,@3,@4,@5,@6,@7];
id a1 = listAry[1];
id b1 = [listAry objectAtIndex:1];
id c1 = [listAry objectAtIndexedSubscript:1];

id a2 = listAry[10];
id b2 = [listAry objectAtIndex:10];
id c2 = [listAry objectAtIndexedSubscript:10];
NSMutableArray *mutListAry = [NSMutableArray arrayWithArray:@[@1,@2,@3,@4,@5,@6,@7]];
id a10 = mutListAry[1];
id b10 = [mutListAry objectAtIndex:1];
id c10 = [mutListAry objectAtIndexedSubscript:1];

id a20 = mutListAry[10];
id b20 = [mutListAry objectAtIndex:10];
id c20 = [mutListAry objectAtIndexedSubscript:10];