Today I was working on a project in which I wanted to \"alias\" an alternative method for all instances of NSArray
, and didn\'t think it would be too difficult with
It's not just that it's a class cluster. NSArray
is toll-free bridged to CFArray
, and you can't swizzle Core Foundation. So this is very unlikely to work in general.
But what are you trying to solve? If you want to add a new method, use a category. They work on class clusters just fine. Modifying the behavior of some built-in on NSArray seems a recipe for disaster (entertaining as it might be as an exercise).
Before going too far, you probably want to at least take a look at CFArray.c and understand how some of the underlying stuff is implemented.
EDIT: While I would never do this in production code, you may get some of what you want by hijacking individual array instances with ISA-swizzling. See ISASwizzle for some example code. The code explanation is in Chapter 20 of iOS:PTL. Search out for "isa swizzle" and you should find more on the net. It's how KVO is implemented. But with NSArray... wow, that's gotta be fragile.
Presumably you have a particular array for which you'd like this behavior. You can get that instance's class object, no matter what it is, and swizzle that quite easily:
[[myArray class] jr_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(objectAtIndex_accordingToMe:) error:nil];
There's also only a few concrete subclasses of NSArray
:
NSArray * trees = [NSArray array];
NSArray * birds = [NSArray arrayWithObjects:@"Albatross", @"Budgerigar", @"Cardinal", nil];
NSMutableArray * dogs = [NSMutableArray arrayWithObjects:@"Airedale", @"Beagle", @"Collie", nil];
NSLog(@"%@ %@ %@", [trees class], [birds class], [dogs class]);
We get __NSArrayI
for the first two and __NSArrayM
for the third, so potentially (this is very fragile) you could use a runtime function to grab the class object by name:
[objc_getClass("__NSArrayI") jr_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(objectAtIndex_accordingToMe:) error:nil];