Runtime拦截可变数组replaceObjectAtIndex:withObject:无效探究

1、故意写一个相关崩溃代码
//拦截1
NSMutableArray *arr1 = @[@"1"].mutableCopy;
[arr1 replaceObjectAtIndex:5 withObject:@"2"];

//拦截2
NSMutableArray *arr2 = @[].mutableCopy;
[arr2 replaceObjectAtIndex:5 withObject:@"1"];

//拦截3
NSMutableArray *arr3 = @[@"1", @"2"].mutableCopy;
[arr3 replaceObjectAtIndex:0 withObject:nil];
2、方法交换拦截
#import "NSMutableArray+HuAvoidCrash.h"
#import <objc/message.h>

@implementation NSMutableArray (HuAvoidCrash)

+(void)load{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        Class class = NSClassFromString(@"__NSArrayM");
        Method old = class_getInstanceMethod(class, @selector(replaceObjectAtIndex:withObject:));
        Method new = class_getInstanceMethod(class, @selector(hu_replaceObjectAtIndex:withObject:));

        if (old && new) {
            method_exchangeImplementations(old, new);
        }
        
    });
}

-(void)hu_replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject{
    
    if (self.count-1 >= index && anObject) {
        
        [self hu_replaceObjectAtIndex:index withObject:anObject];
    }else{
    }
}

@end
3、运行结果

发现拦截1成功,但是拦截2无效,最终奔溃。(但是也走进了这个拦截方法)

4、原因

看下图:断点走进了33行;导致崩溃
但是self确实0个元素;index是5;

为什么呢?

因为:NSUInteger的问题,NSUInteger是无符号的,没有负数

5、解决方案:
-(void)hu_replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject{
    
    if (self.count > index && anObject) {
        
        [self hu_replaceObjectAtIndex:index withObject:anObject];
    }else{
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。