【问题标题】:When reflecting: Should set property or directly set value? (Objective-C)反映时:应该设置属性还是直接设置值? (目标-C)
【发布时间】:2010-11-26 02:07:46
【问题描述】:

我正在为 Objective-c 编写一个 xml 序列化类。
关键是给类一个类类型和一个xml文件。 它应该返回一个带有数据的实例。

我已经让它工作了,它做了很多工作——处理原语(+nsstring)、用户定义的类和nsarray。不处理指针或 C 数组。
显然,这在很大程度上依赖于反射。

问题:当我设置某个类的实例的值时,我应该检查是否存在具有正确名称的属性,还是可以只使用简单的反射设置变量?

这是我目前使用的那种代码:

id newClass = class_createInstance(NSClassFromString(elementName), sizeof(unsigned));
Ivar nameVar = class_getInstanceVariable([newClass class], "name");
if (nameVar != nil)
    object_setIvar(newClass, nameVar, [NSString stringWithString:@"George"]);

另外,在这种分配之后,我应该释放什么吗?

【问题讨论】:

  • 你为什么不使用 NSKeyedArchiver 呢?还是 CoreData?

标签: objective-c reflection properties xml-serialization


【解决方案1】:

呃...你通常不需要需要在运行时进入这么低的位置来执行代码所做的事情。以下是功能齐全的,并且做的事情完全相同:

id newObject = [[NSClassFromString(elementName) alloc] init];
@try {
  [newObject setValue:@"George" forKey:@"name"];
@catch (NSException *e) {
  if ([[e name] isEqualToString:NSUndefinedKeyException]) {
    NSLog(@"%@ does not recognize the property \"name\"", elementName);
  }
}

//... do stuff with newObject
[newObject release];

如果您需要放入其他东西,例如浮点数、整数或结构,您可以将它们装箱成一个 NSValue(或子类),然后将它们传递给setValue:forKey:。例如:

NSNumber * aFloat = [NSNumber numberWithFloat:42.0];
[newObject setValue:aFloat forKey:@"aFloatIvar"];

NSRect frame = NSMakeRect(0, 0, 42, 54);
NSValue * aStruct = [NSValue valueWithBytes:&frame objcType:@encode(NSRect)];
[newObject setValue:aStruct forKey:@"aStructIvar"];

【讨论】:

  • 这段代码的问题是它不适用于原始类型。有办法解决吗?
  • 将你的原语放入一个 NSValue 对象(如 NSValue 或 NSNumber)中,内部会自动将它们拆箱。
  • NSValue 想要“objCType:(const char *)type”。我如何获得类型? (假设没有 class_getInstanceVariable)
  • 代码假定事先知道类型(float,NSRect)。有没有一种简单的方法来获取类变量的原始类型,以便我可以打开它来执行上述操作?
  • @Dror 我不知道。你想用这个做什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-12
  • 1970-01-01
相关资源
最近更新 更多