减少crash的方法hook
2021-06-18 本文已影响0人
哥只是个菜鸟
- 这种方法可能不够严谨,会出现找不到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);
}
+ (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