iOS底层技术

Runtime拦截可变数组replaceObjectAtInde

2019-06-10  本文已影响0人  wg刚
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{
    }
}
上一篇 下一篇

猜你喜欢

热点阅读