Objective c 如何定制NSArray的描述?
我想为NSArray类的Objective c 如何定制NSArray的描述?,objective-c,cocoa,nsarray,Objective C,Cocoa,Nsarray,我想为NSArray类的description方法提供我自己的实现,以便我可以像这样简单地使用它: NSLog(@"%@", @[]); 我的想法是为NSArray提供一个类别,并简单地覆盖description方法。但是它不起作用,因为NSArray是一个类集群,它的真正类是\uu NSArrayI,所以我的类别实现从未被调用。不幸的是,我无法为\uu NSArrayI提供类别,因为此类不可用 当然,我可以子类NSArray并在我的子类中实现此方法,但是,由于NSArray是一个类集群,我必
description
方法提供我自己的实现,以便我可以像这样简单地使用它:
NSLog(@"%@", @[]);
我的想法是为NSArray
提供一个类别,并简单地覆盖description
方法。但是它不起作用,因为NSArray
是一个类集群,它的真正类是\uu NSArrayI
,所以我的类别实现从未被调用。不幸的是,我无法为\uu NSArrayI
提供类别,因为此类不可用
当然,我可以子类NSArray
并在我的子类中实现此方法,但是,由于NSArray
是一个类集群,我必须为一系列不同的方法提供实现,比如objectAtIndex:
,我不想这样做,因为这对于简单地改变数组打印到控制台的方式来说太麻烦了
伙计们,你们有什么想法吗?谢谢
伙计们,你们有什么想法吗?谢谢
我们的想法。解决。。。你必须决定
从中可以看出,您不能只关心说明
。具体来说,从该文件中
Objective-C对象,打印为返回的字符串
descriptionWithLocale:如果可用,或描述其他。阿尔索
使用CFTypeRef对象,返回
CFCopyDescription函数
我们不能对CFTypeRef
对象做太多的工作,除非我们想使用链接器和/或动态加载程序
然而,我们可以对description
和descriptionWithLocale:
做一些事情,尽管这有点粗糙
您也可以考虑<代码>调试描述> /COD>。 这是一种接近你的目标的方法,虽然我认为它是“教育”的,你应该用你最好的判断来决定你是否想走这条路。 首先,您需要确定替换的
description
实现是什么样子的。我们将声明一个类似于这样的description
的简单替换(忽略原始实现)
现在,我们如何使NSArray
实现使用此代码?一种方法是找到NSArray
的所有子类并替换它们的方法
static void swizzleMethod(Class class, SEL selector, IMP newImp) {
Method method = class_getInstanceMethod(class, selector);
if (method) {
IMP origImp = method_getImplementation(method);
if (origImp != newImp) {
method_setImplementation(method, newImp);
}
}
}
static void swizzleArrayDescriptions() {
int numClasses = objc_getClassList(NULL, 0);
if (numClasses <= 0) return;
Class *classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);
numClasses = objc_getClassList(classes, numClasses);
Class target = [NSArray class];
for (int i = 0; i < numClasses; i++) {
for (Class c = classes[i]; c; c = class_getSuperclass(c)) {
if (c == target) {
c = classes[i];
swizzleMethod(c, @selector(description), (IMP)swizzledDescription);
swizzleMethod(c, @selector(descriptionWithLocale:), (IMP)swizzledDescriptionWithLocale);
break;
}
}
}
free(classes);
}
现在,你应该能够玩它,看看你如何相处
作为一个非常简单的测试
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
NSArray *array = @[@"One", @"Two", @3, @"4", @"FIVE", @(6.0), @".7.", @8, @9, @10, @"Eleven" ];
NSLog(@"%@", array);
NSLog(@"%@", [array mutableCopy]);
}
产生这个输出
2015-11-08 14:30:45.501 TestApp[72183:25861219] Array instance (0x6000000c5780) of type __NSArrayI with 11 elements
0x6000000c5780: 0: One
0x6000000c5780: 1: Two
0x6000000c5780: 2: 3
0x6000000c5780: 3: 4
0x6000000c5780: 4: FIVE
0x6000000c5780: 5: 6
0x6000000c5780: 6: .7.
0x6000000c5780: 7: 8
0x6000000c5780: 8: 9
0x6000000c5780: 9: 10
0x6000000c5780: 10: Eleven
2015-11-08 14:30:45.501 TestApp[72183:25861219] Array instance (0x600000045580) of type __NSArrayM with 11 elements
0x600000045580: 0: One
0x600000045580: 1: Two
0x600000045580: 2: 3
0x600000045580: 3: 4
0x600000045580: 4: FIVE
0x600000045580: 5: 6
0x600000045580: 6: .7.
0x600000045580: 7: 8
0x600000045580: 8: 9
0x600000045580: 9: 10
0x600000045580: 10: Eleven
当然,你应该比我做更多的测试,因为我所做的只是在教堂后整理一下,因为它看起来有点有趣(下雨了,所以野餐取消了)
如果需要调用原始实现,则需要创建原始实现的缓存(按类设置键控),并相应地调用它们。但是,对于这样的情况,如果您想要修改返回的字符串,您可能不需要这样做,而且在任何情况下都应该是直接的
另外,请注意关于swizzling的一般注意事项,在使用类集群时,这些注意事项会更加突出
注意,您也可以这样做,在运行时创建自定义子类。您甚至可以以正常方式将您的子类定义为
NSArray
的直接子类,然后在不影响任何非您的类的情况下切换它们的类型。。。或者一堆不同的东西。。。记住Objective运行时是您的朋友。您已经大致了解了各种选项和缺点。我认为没有其他选择。我想您可以使用swizzle,但您可能不得不接受不完全覆盖,除非您可以完全覆盖所有类集群成员。请记住NSMutableArray也是一个类群集:)如果您想在特定设计中为特定数组执行此操作,那么可能最简单的方法是编写一个方法/函数,以在数组的所有者(无论是数组的ViewController还是包装器对象)中生成描述,或者在其他一些专门用于描述此集合的特殊类中-(NSString)descripbemyarray:(NSArray)array{…}为什么要提供自定义的描述
?目标是什么?对于这个问题,可能有一个比将功能附加到基集合类上更好的解决方案。
@implementation AppDelegate
+ (void)initialize {
if (self == [AppDelegate class]) {
swizzleArrayDescriptions();
}
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
NSArray *array = @[@"One", @"Two", @3, @"4", @"FIVE", @(6.0), @".7.", @8, @9, @10, @"Eleven" ];
NSLog(@"%@", array);
NSLog(@"%@", [array mutableCopy]);
}
2015-11-08 14:30:45.501 TestApp[72183:25861219] Array instance (0x6000000c5780) of type __NSArrayI with 11 elements
0x6000000c5780: 0: One
0x6000000c5780: 1: Two
0x6000000c5780: 2: 3
0x6000000c5780: 3: 4
0x6000000c5780: 4: FIVE
0x6000000c5780: 5: 6
0x6000000c5780: 6: .7.
0x6000000c5780: 7: 8
0x6000000c5780: 8: 9
0x6000000c5780: 9: 10
0x6000000c5780: 10: Eleven
2015-11-08 14:30:45.501 TestApp[72183:25861219] Array instance (0x600000045580) of type __NSArrayM with 11 elements
0x600000045580: 0: One
0x600000045580: 1: Two
0x600000045580: 2: 3
0x600000045580: 3: 4
0x600000045580: 4: FIVE
0x600000045580: 5: 6
0x600000045580: 6: .7.
0x600000045580: 7: 8
0x600000045580: 8: 9
0x600000045580: 9: 10
0x600000045580: 10: Eleven