Objective-C method_exchangeImplementations result is not as expected

Viewed 44

I'm learning Objective-C runtime, and try to use method_exchangeImplementations to exchange addObject: method and removeObject: method of NSMutableArray.

My code like this:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Method removeMethod = class_getInstanceMethod(NSMutableArray.class, @selector(removeObject:));
        Method addMethod = class_getInstanceMethod(NSMutableArray.class, @selector(addObject:));
        method_exchangeImplementations(addMethod, removeMethod);
        NSMutableArray *array = [[NSMutableArray alloc] init];
        NSObject *obj = [[NSObject alloc] init];
        [array removeObject:obj];
        NSLog(@"%lu", (unsigned long)array.count); // expect print 1, actual print 1
        [array addObject:obj];
        NSLog(@"%lu", (unsigned long)array.count); // expect print 0, actual print 2
    }
    return 0;
}

I expect exchange add/remove function, but seems like only removeObject: has been exchange to addObject: , addObject: still is addObject to array, now I have two addObject method of NSMutableArray

I'm not sure the reason. I try to exchange other method like uppercaseString/lowercaseString of NSString, that work correct.

1 Answers

OK, I solved problem. Thanks @Willeke for the tip.

The real class of my array is not NSMutableArray, so use NSMutableArray.class in class_getInstanceMethod can't get correct method. Use [array class] is the answer.

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSMutableArray *array = [[NSMutableArray alloc] init];
        Method removeMethod = class_getInstanceMethod([array class], @selector(removeObject:));
        Method addMethod = class_getInstanceMethod([array class], @selector(addObject:));
        method_exchangeImplementations(addMethod, removeMethod);
        NSObject *obj = [[NSObject alloc] init];
        [array removeObject:obj];
        NSLog(@"%lu", (unsigned long)array.count); // expect print 1, actual print 1
        [array addObject:obj];
        NSLog(@"%lu", (unsigned long)array.count); // expect print 0, actual print 0
    }
    return 0;
}
Related