#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSArray (PreventCrash)
@end
@interface NSMutableArray (PreventCrash)
@end
NS_ASSUME_NONNULL_END
#import "NSArray+PreventCrash.h"
#import <objc/runtime.h>
@implementation NSArray (PreventCrash)
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//处理数组越界crash
NSArray* classNameArray = @[@"__NSArrayI",@"__NSArrayM",@"__NSSingleObjectArrayI"];
[classNameArray enumerateObjectsUsingBlock:^(NSString* className, NSUInteger idx, BOOL * _Nonnull stop) {
Method objectAtIndexedSubscript = class_getInstanceMethod(objc_getClass(className.UTF8String), @selector(objectAtIndexedSubscript:));
NSString* swizzingSelName = [className stringByAppendingString:@"_swizzing_objectAtIndexedSubscript:"];
SEL swizzingSEL = NSSelectorFromString(swizzingSelName);
Method swizzingObjectAtIndexedSubscript = class_getInstanceMethod(self, swizzingSEL);
BOOL addSuccess = class_addMethod(self, @selector(objectAtIndexedSubscript:), method_getImplementation(swizzingObjectAtIndexedSubscript), method_getTypeEncoding(swizzingObjectAtIndexedSubscript));
if (addSuccess) {
class_replaceMethod(self, swizzingSEL, method_getImplementation(objectAtIndexedSubscript), method_getTypeEncoding(objectAtIndexedSubscript));
}else{
method_exchangeImplementations(objectAtIndexedSubscript, swizzingObjectAtIndexedSubscript);
}
}];
});
}
#pragma mark - 数组越界方法
- (id)__NSArrayI_swizzing_objectAtIndexedSubscript:(NSUInteger)idx{
if (idx < self.count) {
return self[idx];
}
return nil;
}
- (id)__NSArrayM_swizzing_objectAtIndexedSubscript:(NSUInteger)idx{
if (idx < self.count) {
return self[idx];
}
return nil;
}
- (id)__NSSingleObjectArrayI_swizzing_objectAtIndexedSubscript:(NSUInteger)idx{
if (idx < self.count) {
return self[idx];
}
return nil;
}
@end
@implementation NSMutableArray (PreventCrash)
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//处理数组add nil
Class mutableArrayClass = objc_getClass(@"__NSArrayM".UTF8String);
SEL mutableInsertSEL = @selector(insertObject:atIndex:);
SEL swizzingMutableInsertSEL = @selector(__NSArrayM_insertObject:atIndex:);
Method mutableInsertMethod = class_getInstanceMethod(mutableArrayClass, mutableInsertSEL);
Method swizzingMutableInsertMethod = class_getInstanceMethod(self, swizzingMutableInsertSEL);
BOOL success = class_addMethod(mutableArrayClass, mutableInsertSEL, method_getImplementation(swizzingMutableInsertMethod), method_getTypeEncoding(swizzingMutableInsertMethod));
if (success) {
class_addMethod(mutableArrayClass, swizzingMutableInsertSEL, method_getImplementation(mutableInsertMethod), method_getTypeEncoding(mutableInsertMethod));
}else{
method_exchangeImplementations(mutableInsertMethod, swizzingMutableInsertMethod);
}
});
}
#pragma mark - NSArrayM
- (void)__NSArrayM_insertObject:(id)anObject atIndex:(NSUInteger)index{
if (!anObject) return;
[self __NSArrayM_insertObject:anObject atIndex:index];
}
@end