NSArray中的__NSArray0、__NSSingleObjectArrayI、__NSArrayI,用runtime交换里面的方法

有一篇比较详细的文章说这三个,这里总结下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);
    });
}

最后那个方法

你可能感兴趣的:(ios开发,NSArray,__NSArray0,__NSArrayI)