【发布时间】:2009-10-27 14:52:00
【问题描述】:
有没有办法获得一个类的所有键值对的字典之类的东西?
【问题讨论】:
标签: objective-c cocoa cocoa-touch
有没有办法获得一个类的所有键值对的字典之类的东西?
【问题讨论】:
标签: objective-c cocoa cocoa-touch
您必须使用Objective-C Runtime functions 自行开发。这是一些非常基本的示例代码。请注意,获取类的 ivars 并不能获取其超类的 ivars。您需要明确地执行此操作,但这些函数都在运行时中。
#import <objc/objc-runtime.h>
#include <inttypes.h>
#include <Foundation/Foundation.h>
@interface Foo : NSObject
{
int i1;
}
@end
@implementation Foo
@end
@interface Bar : Foo
{
NSString* s1;
}
@end
@implementation Bar
@end
int main(int argc, char** argv)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
unsigned int count;
Ivar* ivars = class_copyIvarList([Bar class], &count);
for(unsigned int i = 0; i < count; ++i)
{
NSLog(@"%@::%s", [Bar class], ivar_getName(ivars[i]));
}
free(ivars);
[pool release];
}
【讨论】:
class_copyIvarList 的名称中有copy,因此您负责清理内存。因此,您还需要free(ivars);。
我不确定是否只是 ivars,但如果您将它们定义为属性,则可以访问类上的可用属性。
我已经在几个项目中使用 SQLitePersistentObjects,它有一些有用的代码可以获取类上定义的属性,以便在确定与 sqlite 之间的序列化时使用。
它使用函数 class_copyPropertyList 来获取类的可用属性列表。
更具体地说:
+(NSDictionary *)propertiesWithEncodedTypes
{
// DO NOT use a static variable to cache this, it will cause problem with subclasses of classes that are subclasses of SQLitePersistentObject
// Recurse up the classes, but stop at NSObject. Each class only reports its own properties, not those inherited from its superclass
NSMutableDictionary *theProps;
if ([self superclass] != [NSObject class])
theProps = (NSMutableDictionary *)[[self superclass] propertiesWithEncodedTypes];
else
theProps = [NSMutableDictionary dictionary];
unsigned int outCount;
objc_property_t *propList = class_copyPropertyList([self class], &outCount);
int i;
// Loop through properties and add declarations for the create
for (i=0; i < outCount; i++)
{
objc_property_t * oneProp = propList + i;
NSString *propName = [NSString stringWithUTF8String:property_getName(*oneProp)];
NSString *attrs = [NSString stringWithUTF8String: property_getAttributes(*oneProp)];
NSArray *attrParts = [attrs componentsSeparatedByString:@","];
if (attrParts != nil)
{
if ([attrParts count] > 0)
{
NSString *propType = [[attrParts objectAtIndex:0] substringFromIndex:1];
[theProps setObject:propType forKey:propName];
}
}
}
free(propList);
return theProps;
}
这将返回一个属性字典 - 您需要对返回的结果进行一些调查,但如果您使用属性,您应该能够获得所需的内容。
【讨论】:
是的,完全有可能:
int numIvars = 0;
Ivar * ivars = class_copyIvarList([anInstanceOfAClass class], &numIvars);
NSMutableDictionary * pairs = [NSMutableDictionary dictionary];
for (int i = 0; i < numIvars; ++i) {
Ivar ivar = ivars[i];
NSString * ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
id ivarValue = [anInstanceOfAClass valueForKey:ivarName];
[pairs setObject:ivarValue forKey:ivarName];
}
free(ivars);
NSLog(@"%@", pairs);
【讨论】: