有一篇比较详细的文章说这三个,这里总结下https://www.aopod.com/2017/02/24/class-clusters/
想写个类别把系统的NSArray中的方法替换掉,最多的是这么写
Class myClass = NSClassFromString(@"__NSArrayI");
Method safeMethod=class_getInstanceMethod (self, @selector(objectAtSafeIndexI:));
Method unsafeMethod=class_getInstanceMethod (myClass, @selector(objectAtIndex:));
method_exchangeImplementations(unsafeMethod, safeMethod);
-(id)safeObjectAtIndex:(NSUInteger)index{
NSLog(@"safeObjectAtIndex-->>%@--->>%@",@(index),@(self.count));
if (index > (self.count - 1)) {
// NSAssert(NO, @"beyond the boundary");
return nil;
}
else{
return [self safeObjectAtIndex:index];
}
}
后来发现个数为1个的时候或者为0个的时候,还是会闪退,查看了下原来不止一个子类__NSArrayI
还有__NSSingleObjectArrayI和其他的
如题所示,后面的三个为NSArray的子类,NSMutableArray则不做说明
NSArray *placeholder = [NSArray alloc];
NSArray *arr1 = [placeholder init];
NSArray *arr2 = [placeholder initWithObjects:@0, nil];
NSArray *arr3 = [placeholder initWithObjects:@0, @1, nil];
NSArray *arr4 = [placeholder initWithObjects:@0, @1, @2, nil];
NSLog(@"placeholder: %s", object_getClassName(placeholder)); // placeholder: __NSPlaceholderArray
NSLog(@"arr1: %s", object_getClassName(arr1)); // arr1: __NSArray0
NSLog(@"arr2: %s", object_getClassName(arr2)); // arr2: __NSSingleObjectArrayI
NSLog(@"arr3: %s", object_getClassName(arr3)); // arr3: __NSArrayI
NSLog(@"arr4: %s", object_getClassName(arr4)); // arr4: __NSArrayI
所以交换方法需要把几个全部写好,例如
+(void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class myClass = NSClassFromString(@"__NSArrayI");
Method safeMethod=class_getInstanceMethod (self, @selector(objectAtSafeIndexI:));
Method unsafeMethod=class_getInstanceMethod (myClass, @selector(objectAtIndex:));
method_exchangeImplementations(unsafeMethod, safeMethod);
Class myClass0 = NSClassFromString(@"__NSSingleObjectArrayI");
Method safeMethod0 = class_getInstanceMethod (self, @selector(safeObjectAtIndex:));
Method unsafeMethod0 = class_getInstanceMethod (myClass0, @selector(objectAtIndex:));
method_exchangeImplementations(safeMethod0, unsafeMethod0);
Class myClass1 = NSClassFromString(@"__NSArray0");
Method safeMethod1 = class_getInstanceMethod (self, @selector(objectAtSafeIndex0:));
Method unsafeMethod1 = class_getInstanceMethod (myClass1, @selector(objectAtIndex:));
method_exchangeImplementations(safeMethod1, unsafeMethod1);
Method old = class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), @selector(insertObject:atIndex:));
Method new = class_getInstanceMethod(self, @selector(insertSaveObject:atIndex:));
if (!old || !new) {
return;
}
method_exchangeImplementations(old, new);
});
}
最后那个方法