有没有办法对NSArray(或其他类集群)进行猴子补丁或调整?

时间:2012-08-01 01:38:34

标签: objective-c cocoa nsarray monkeypatching swizzling

今天我正在开展一个项目,我希望为NSArray的所有实例“替换”替代方法,并且认为某些good old-fashioned method swizzling.不会太困难

我爆发了JRSwizzle和......

[NSArray jr_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(objectAtIndex_accordingToMe:) error:nil];

为了清楚起见,我将其与NSArray上的相应类别配对,这是一种名为objectAtIndex_accordingToMe:的实例方法。

但是,我只是在同一个旧索引上获得相同的旧对象。叹。最终,我发现虽然没有抛出任何错误 - 我不会实现这些结果due to the fact that NSArray is a class cluster

我想我的问题更多的是不愿意接受“这个”真的是试图覆盖NSArray方法的终点。我的意思是,来吧这是NSArray ..人们一定想用它来捣乱,不是吗?一个会认为 Apple的基础课程将成为各地流氓的主要目标!

那么,有没有办法改变,别名,monkey-patch,覆盖或以其他方式使用... NSArray等(没有子类化)?

2 个答案:

答案 0 :(得分:4)

这不仅仅是一个类集群。 NSArray免费与CFArray桥接,您无法调动Core Foundation。所以这一般不太可能奏效。

但是你想要解决什么?如果要添加新方法,请使用类别。他们在类集群上工作很好。修改一些内置在NSArray上的行为似乎是灾难的一个方法(娱乐,因为它可能是一个练习)。

之前,你可能想要至少看一下CFArray.c并了解一些底层的东西是如何实现的。


编辑:虽然我不会在生产代码中执行此操作,但您可以通过使用ISA调配来劫持单个数组实例,从而获得所需的一些内容。有关示例代码,请参阅ISASwizzle。代码解释在iOS:PTL的第20章中。搜索“isa swizzle”,你应该在网上找到更多。这就是KVO的实施方式。但是对于NSArray ......哇,这一定是脆弱的。

答案 1 :(得分:3)

据推测,你有一个特定的数组,你喜欢这种行为。您可以获取该实例的类对象,无论它是什么,并且很容易调整:

[[myArray class] jr_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(objectAtIndex_accordingToMe:) error:nil];

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]);

我们获得前两个__NSArrayI和第三个__NSArrayM,因此可能(这是非常脆弱)您可以使用运行时函数按名称获取类对象:

[objc_getClass("__NSArrayI") jr_swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(objectAtIndex_accordingToMe:) error:nil];