runtime使用之防止数组越界

面试时曾被问到一个问题,如何使用runtime防止数组越界?当时想到的是用分类重写系统的ObjectAtIndex:方法就好了,何必多此一举,后来在学习runtime中认识到,使用runtime是一种更好的方式。

添加数组的分类,.h文件不需要操作。.m文件如下:

#import "NSArray+CPFSafe.h"

#import

@implementation NSArray (CPFSafe)

+ (void)load

{

    //方法交换应该保证在程序中只执行一次。

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        Method origin_method = class_getInstanceMethod([NSArray class], @selector(objectAtIndex:));

        Method new_method = class_getInstanceMethod([self class], @selector(safeObjectAtIndex:));

        method_exchangeImplementations(origin_method, new_method);

        // 对于数组 arr[10] 这种形式的使用,OC会调用objectAtIndexedSubscript:方法

        Method sub_origin_method = class_getInstanceMethod([NSArray class], @selector(objectAtIndexedSubscript:));

        Method sub_new_method = class_getInstanceMethod([self class], @selector(safeObjectAtIndexedSubscript:));

        method_exchangeImplementations(sub_origin_method, sub_new_method);


    });

}

-(NSObject *)safeObjectAtIndex:(NSUInteger)index

{

    if (index > self.count -1)

    {

        return nil;

    }else

    {

        //不会产生递归调用,还记得我们方法的实现交换了吗

        return [self safeObjectAtIndex:index];

    }

}

- (NSObject *)safeObjectAtIndexedSubscript:(NSUInteger)index

{

    if (index > self.count -1)

    {

        return nil;

    }else

    {

        return [self safeObjectAtIndexedSubscript:index];

    }

}

@end

使用runtime 函数class_getInstanceMethod(Class,@selecter)实时获取方法,然后使用method_exchangeImplementations函数交换自己添加的方法和系统方法的实现。

自己的方法里对越界做一些处理。

好了,检验一下

调用的地方需要引入头文件

#import "NSArray+CPFSafe.h"

NSArray *arr = @[@"0",@"new"];

    NSObject *obj = arr[1];

    NSObject *obj2 = arr[3];

    NSLog(@"obj:%@",obj);

    NSLog(@"obj:%@",obj2);

打印结果:

2018-10-30 16:21:48.126 runtime[1550:124093] obj:new

2018-10-30 16:21:48.127 runtime[1550:124093] obj:(null)

不会发生崩溃错误。

你可能感兴趣的:(runtime使用之防止数组越界)