1

我试图找出一种在给定对象的情况下提取属性名称的方法,而不是所有属性的名称,而是一个特定的名称。为了做到这一点,我在课堂上实现了这个方法:

-(NSString *)keyForProperty:(NSObject *)theProperty{
unsigned int propertyCount = 0;
objc_property_t * properties = class_copyPropertyList([self class], &propertyCount);

for (unsigned int i = 0; i < propertyCount; ++i) {
    objc_property_t property = properties[i];

    NSString *name=[NSString stringWithUTF8String:property_getName(property)];

    NSObject * propertyValue=[self valueForKey:name];
    if(propertyValue==theProperty){
        free(properties);
        return name;

    }
}
free(properties);

return nil;

}

它的工作原理是这样的:我已经和 A 类的对象 foo 知道属性 p 的名称我做了这样的事情:

NSString *name=[foo keyForProperty:foo.p]; 

问题是,在我的 A 类中,我有两个属性 p1 和 p2 都是 NSString,并且在 A 的 init 方法中,我将 @"" 分配给它们。问题是 p1 和 p2 然后指向相同的内存位置,因此当我这样做时:

 NSString *name=[foo keyForProperty:foo.p1];

 NSString *name=[foo keyForProperty:foo.p2];

我对他们两个都得到了相同的结果。在将 @"" 分配给两个属性时如何防止这种情况发生的任何想法?你有没有更好的实现方式?要求是给定的和对象:

 A* foo=[[A alloc]init];

A 类的我必须能够获得特定的属性名称。

谢谢你。

解释为什么我需要这个:

我有一个 UIViewController 子类 TextEditingVC,它所做的只是接收和编辑对象以及要编辑的属性名称,并且编辑过程由 TextEditingVC 实例自动管理,我所要做的就是:

A *foo;

//lets edit property p
NSString *key=[foo keyForProperty:foo.p];
TextEditingVC *theVC=[TextEditingVC alloc]initWithEditableObject:foo withEditionKey:key];
//present theVC in some way

这个 TextEditingVC 应该能够编辑任何对象的 NSString 属性。这个想法是使 TextEditingVC 尽可能通用,因为在我的应用程序中,我必须编辑作为各种类的属性的 NSString。

当然我可以简单地使用:

NSString *key=@"p";

代替:

NSString * key=[foo keyForProperty:foo.p];

但在那种情况下,字符串将在我的代码中被硬编码,我想避免它,为了良好的编程实践,或者我在这种特殊情况下试图避免硬编码字符串是错误的?

4

2 回答 2

1

我不知道实现你想要的东西的方法。但是,您也许可以使用硬编码的键名使访问更加安全。例如,您可以制作如下宏:

#define CHECKED_PROPERTY(obj, prop) ((void)((obj).prop), @#prop)

此宏使用逗号运算符扩展为表达式。首先obj.prop评估子表达式,但其结果被丢弃。这样做的目的只是让编译器验证表达式,所以如果prop不是obj. 第二个子表达式prop使用预处理器运算符对参数进行字符串化#。它将@字符串文字转换为Objective-CNSString文字的前缀。

并像这样使用它:

NSString* key = CHECKED_PROPERTY(foo, p);

这扩展为:

NSString* key = ((void)((foo).p), @"p");

这将评估foo.p但忽略结果并具有设置key为的效果@"p"

然后,如果您重构并重命名px,重构引擎(如果它真的很聪明)会发现它需要对上述内容做一些事情,或者如果重构错过了它,至少编译器会抱怨。p(但是,如果您将其重命名为xq,则它会下降p。)

于 2013-09-05T19:37:45.673 回答
0

你可以不同地初始化你的两个属性(p1 = @"v1", p2 = @"v2")

于 2013-09-05T17:50:39.030 回答