减少crash的方法hook

  • 这种方法可能不够严谨,会出现找不到originalSelector方法的情况
- (void)hookInstanceMethod:(SEL)originalSelector AndSelector:(SEL)swizzledSelector {
    Method originMethod = class_getInstanceMethod(self.class, originalSelector);
    Method newMethod = class_getInstanceMethod(self.class, swizzledSelector);
    method_exchangeImplementations(originMethod, newMethod);
}
  • 推荐第二种,借鉴https://www.jianshu.com/p/37ebc1488ed4
+ (void)SwizzledMethod:(Class)class OriginalSelector:(SEL)originalSelector newSelector:(SEL)newSelector {
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method newMethod = class_getInstanceMethod(class, newSelector);
//    if (originMethod && newMethod) {
//        method_exchangeImplementations(originMethod, newMethod);
//    }
    
    //class_addMethod 添加的SEL是 originalSelector ,IMP 是 method_getImplementation(originalMethod),我称他们为原配,
       //如果本类中,已经有 originalSelector,再添加 originalSelector, 肯定返回NO,添加失败,那就直接交换了,跟第一版hook流程一模一样了,
       //如果本类中,没有此SEL,那就会去父类里找,返回的就是父类里的信息,然后将父类的信息,添加到本类中,就相当于,本类完全的继承了父类的方法,
       BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
       if (didAddMethod) {
           //添加成功后,本类中,已经有一个originalSelector方法了
           //我们第一次获得originalMethod是返回父类的originalMethod
           //我们需要再重新获得一下originalMethod,这次返回的不是父类的originalMethod
           //而是我们刚刚class_addMethod添加的到本类的originalMethod
           
           originalMethod = class_getInstanceMethod(class, originalSelector);
       }
       
       //走到这,就证明了,本类中肯定已经有这两个方法了,那就这样直接交换吧。
       method_exchangeImplementations(newMethod, originalMethod);
}
  • 这里只贴避免数组越界的例子,(其他字典,字符串类似),这里注意替换方法的class不能是[NSArray class],之前一直方法替换不成功,问题出在这里
 swizzling_exchangeMethod([NSArray class], @selector(objectAtIndex:), 
swizzling_exchangeMethod(objc_getClass("__NSArray0"), @selector(objectAtIndex:), 
image.png

+ (void)load {
    //__NSArrayI:不可变,2个或2以上元素  __NSArray0:空数组  __NSArrayM:可变  __NSSingleObjectArrayI:只有单个元素
//    [array objectAtIndex:8]
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSArrayI") OriginalSelector:@selector(objectAtIndex:) newSelector:@selector(array_objectAtIndex:)];
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSArray0") OriginalSelector:@selector(objectAtIndex:) newSelector:@selector(empty_objectAtIndex:)];
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSArrayM") OriginalSelector:@selector(objectAtIndex:) newSelector:@selector(arrayM_objectAtIndex:)];
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSSingleObjectArrayI") OriginalSelector:@selector(objectAtIndex:) newSelector:@selector(singleArray_objectAtIndex:)];

    //array[8]
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSArrayI") OriginalSelector:@selector(objectAtIndexedSubscript:) newSelector:@selector(array_objectAtIndexedSubscript:)];
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSArray0") OriginalSelector:@selector(objectAtIndexedSubscript:) newSelector:@selector(empty_objectAtIndexedSubscript:)];
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSArrayM") OriginalSelector:@selector(objectAtIndexedSubscript:) newSelector:@selector(arrayM_objectAtIndexedSubscript:)];
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSSingleObjectArrayI") OriginalSelector:@selector(objectAtIndexedSubscript:) newSelector:@selector(singleArray_objectAtIndexedSubscript:)];

    [SwizzledHelper SwizzledMethod:objc_getClass("__NSArrayM") OriginalSelector:@selector(removeObjectAtIndex:) newSelector:@selector(arrayM_removeObjectAtIndex:)];
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSArrayM") OriginalSelector:@selector(replaceObjectAtIndex:withObject:) newSelector:@selector(arrayM_replaceObjectAtIndex:withObject:)];
    [SwizzledHelper SwizzledMethod:objc_getClass("__NSArrayM") OriginalSelector:@selector(insertObject:atIndex:) newSelector:@selector(arrayM_insertObject:atIndex:)];
}

- (id)array_objectAtIndex:(NSUInteger)index {
    if (index < self.count) {
        return [self array_objectAtIndex:index];
    } else {
        return nil;
    }
}

- (id)empty_objectAtIndex:(NSUInteger)index {
    if (index < self.count) {
        return [self empty_objectAtIndex:index];
    } else {
        return nil;
    }
}

- (id)arrayM_objectAtIndex:(NSUInteger)index {
    if (index < self.count) {
        return [self arrayM_objectAtIndex:index];
    } else {
        return nil;
    }
}

- (id)singleArray_objectAtIndex:(NSUInteger)index {
    if (index < self.count) {
        return [self singleArray_objectAtIndex:index];
    } else {
        return nil;
    }
}

- (id)array_objectAtIndexedSubscript:(NSUInteger)index {
    if (index < self.count) {
        return [self array_objectAtIndexedSubscript:index];
    } else {
        return nil;
    }
}

- (id)empty_objectAtIndexedSubscript:(NSUInteger)index {
    if (index < self.count) {
        return [self empty_objectAtIndexedSubscript:index];
    } else {
        return nil;
    }
}

- (id)arrayM_objectAtIndexedSubscript:(NSUInteger)index {
    if (index < self.count) {
        return [self arrayM_objectAtIndexedSubscript:index];
    } else {
        return nil;
    }
}

- (id)singleArray_objectAtIndexedSubscript:(NSUInteger)index {
    if (index < self.count) {
        return [self singleArray_objectAtIndexedSubscript:index];
    } else {
        return nil;
    }
}

- (void)arrayM_insertObject:(id)object atIndex:(NSUInteger)index {
    if (object && index <= self.count) {
        [self arrayM_insertObject:object atIndex:index];
    }
}

- (void)arrayM_removeObjectAtIndex:(NSUInteger)index {
    if (index < self.count) {
         [self arrayM_removeObjectAtIndex:index];
    }
}

- (void)arrayM_replaceObjectAtIndex:(NSUInteger)index withObject:(id)object {
    if (object && index < self.count) {
         [self arrayM_replaceObjectAtIndex:index withObject:object];
    }
}


@end

你可能感兴趣的:(减少crash的方法hook)