获取Objective-C中的对象属性列表

获取Objective-C中的对象属性列表

如何在Objective-C中获取给定对象属性的列表(以NSArray或的形式NSDictionary)?

想象一下下面的场景:我已经定义了一个只扩展的父类NSObject,它将a NSString,a BOOL和一个NSData对象作为属性。然后我有几个扩展这个父类的类,每个类都添加了很多不同的属性。

有没有什么方法可以在类上实现一个遍历整个对象的实例方法,然后返回NSArray每个(子)类属性的一个,因为NSStrings不在父类上,所以我以后可以使用这些NSString对于KVC?


慕标5832272
浏览 621回答 3
3回答

拉丁的传说

我自己设法得到了答案。通过使用Obj-C运行时库,我可以按照我想要的方式访问属性:-&nbsp;(void)myMethod&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;int&nbsp;outCount,&nbsp;i; &nbsp;&nbsp;&nbsp;&nbsp;objc_property_t&nbsp;*properties&nbsp;=&nbsp;class_copyPropertyList([self&nbsp;class],&nbsp;&outCount); &nbsp;&nbsp;&nbsp;&nbsp;for(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;outCount;&nbsp;i++)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objc_property_t&nbsp;property&nbsp;=&nbsp;properties[i]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;char&nbsp;*propName&nbsp;=&nbsp;property_getName(property); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(propName)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;char&nbsp;*propType&nbsp;=&nbsp;getPropertyType(property); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSString&nbsp;*propertyName&nbsp;=&nbsp;[NSString&nbsp;stringWithCString:propName &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;encoding:[NSString&nbsp;defaultCStringEncoding]]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSString&nbsp;*propertyType&nbsp;=&nbsp;[NSString&nbsp;stringWithCString:propType &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;encoding:[NSString&nbsp;defaultCStringEncoding]]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;free(properties);}这要求我制作一个'getPropertyType'C函数,它主要取自Apple代码示例(现在不能记住确切的来源):static&nbsp;const&nbsp;char&nbsp;*getPropertyType(objc_property_t&nbsp;property)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;char&nbsp;*attributes&nbsp;=&nbsp;property_getAttributes(property); &nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;buffer[1&nbsp;+&nbsp;strlen(attributes)]; &nbsp;&nbsp;&nbsp;&nbsp;strcpy(buffer,&nbsp;attributes); &nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*state&nbsp;=&nbsp;buffer,&nbsp;*attribute; &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;((attribute&nbsp;=&nbsp;strsep(&state,&nbsp;","))&nbsp;!=&nbsp;NULL)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(attribute[0]&nbsp;==&nbsp;'T')&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(strlen(attribute)&nbsp;<=&nbsp;4)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(const&nbsp;char&nbsp;*)[[NSData&nbsp;dataWithBytes:(attribute&nbsp;+&nbsp;3)&nbsp;length:strlen(attribute)&nbsp;-&nbsp;4]&nbsp;bytes]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;"@";}

明月笑刀无情

它实际上并不总是以0结束字符串。这可能会导致意外的结果,比如在尝试将其转换为UTF8时崩溃(我实际上有一个非常令人讨厌的崩溃因为这个。很有趣的调试它^^)。我通过实际从属性获取NSString然后调用cStringUsingEncoding来修复它:这就像现在的魅力。(也适用于ARC,至少对我而言)所以这是我现在的代码版本://&nbsp;PropertyUtil.h#import&nbsp;@interface&nbsp;PropertyUtil&nbsp;:&nbsp;NSObject+&nbsp;(NSDictionary&nbsp;*)classPropsFor:(Class)klass;@end//&nbsp;PropertyUtil.m#import&nbsp;"PropertyUtil.h"#import&nbsp;<objc/runtime.h>@implementation&nbsp;PropertyUtilstatic&nbsp;const&nbsp;char&nbsp;*getPropertyType(objc_property_t&nbsp;property)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;char&nbsp;*attributes&nbsp;=&nbsp;property_getAttributes(property); &nbsp;&nbsp;&nbsp;&nbsp;//printf("attributes=%s\n",&nbsp;attributes); &nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;buffer[1&nbsp;+&nbsp;strlen(attributes)]; &nbsp;&nbsp;&nbsp;&nbsp;strcpy(buffer,&nbsp;attributes); &nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*state&nbsp;=&nbsp;buffer,&nbsp;*attribute; &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;((attribute&nbsp;=&nbsp;strsep(&state,&nbsp;","))&nbsp;!=&nbsp;NULL)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(attribute[0]&nbsp;==&nbsp;'T'&nbsp;&&&nbsp;attribute[1]&nbsp;!=&nbsp;'@')&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;it's&nbsp;a&nbsp;C&nbsp;primitive&nbsp;type: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;you&nbsp;want&nbsp;a&nbsp;list&nbsp;of&nbsp;what&nbsp;will&nbsp;be&nbsp;returned&nbsp;for&nbsp;these&nbsp;primitives,&nbsp;search&nbsp;online&nbsp;for &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"objective-c"&nbsp;"Property&nbsp;Attribute&nbsp;Description&nbsp;Examples" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;apple&nbsp;docs&nbsp;list&nbsp;plenty&nbsp;of&nbsp;examples&nbsp;of&nbsp;what&nbsp;you&nbsp;get&nbsp;for&nbsp;int&nbsp;"i",&nbsp;long&nbsp;"l",&nbsp;unsigned&nbsp;"I",&nbsp;struct,&nbsp;etc. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSString&nbsp;*name&nbsp;=&nbsp;[[NSString&nbsp;alloc]&nbsp;initWithBytes:attribute&nbsp;+&nbsp;1&nbsp;length:strlen(attribute)&nbsp;-&nbsp;1&nbsp;encoding:NSASCIIStringEncoding]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(const&nbsp;char&nbsp;*)[name&nbsp;cStringUsingEncoding:NSASCIIStringEncoding]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if&nbsp;(attribute[0]&nbsp;==&nbsp;'T'&nbsp;&&&nbsp;attribute[1]&nbsp;==&nbsp;'@'&nbsp;&&&nbsp;strlen(attribute)&nbsp;==&nbsp;2)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;it's&nbsp;an&nbsp;ObjC&nbsp;id&nbsp;type: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;"id"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if&nbsp;(attribute[0]&nbsp;==&nbsp;'T'&nbsp;&&&nbsp;attribute[1]&nbsp;==&nbsp;'@')&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;it's&nbsp;another&nbsp;ObjC&nbsp;object&nbsp;type: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSString&nbsp;*name&nbsp;=&nbsp;[[NSString&nbsp;alloc]&nbsp;initWithBytes:attribute&nbsp;+&nbsp;3&nbsp;length:strlen(attribute)&nbsp;-&nbsp;4&nbsp;encoding:NSASCIIStringEncoding]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(const&nbsp;char&nbsp;*)[name&nbsp;cStringUsingEncoding:NSASCIIStringEncoding]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;"";}+&nbsp;(NSDictionary&nbsp;*)classPropsFor:(Class)klass{ &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(klass&nbsp;==&nbsp;NULL)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;NSMutableDictionary&nbsp;*results&nbsp;=&nbsp;[[NSMutableDictionary&nbsp;alloc]&nbsp;init]; &nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;int&nbsp;outCount,&nbsp;i; &nbsp;&nbsp;&nbsp;&nbsp;objc_property_t&nbsp;*properties&nbsp;=&nbsp;class_copyPropertyList(klass,&nbsp;&outCount); &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;outCount;&nbsp;i++)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objc_property_t&nbsp;property&nbsp;=&nbsp;properties[i]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;char&nbsp;*propName&nbsp;=&nbsp;property_getName(property); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(propName)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;char&nbsp;*propType&nbsp;=&nbsp;getPropertyType(property); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSString&nbsp;*propertyName&nbsp;=&nbsp;[NSString&nbsp;stringWithUTF8String:propName]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSString&nbsp;*propertyType&nbsp;=&nbsp;[NSString&nbsp;stringWithUTF8String:propType]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[results&nbsp;setObject:propertyType&nbsp;forKey:propertyName]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;free(properties); &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;returning&nbsp;a&nbsp;copy&nbsp;here&nbsp;to&nbsp;make&nbsp;sure&nbsp;the&nbsp;dictionary&nbsp;is&nbsp;immutable &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;[NSDictionary&nbsp;dictionaryWithDictionary:results];}@end
打开App,查看更多内容
随时随地看视频慕课网APP