如何使用键值编码判断对象是否存在密钥?

Ted*_*Ted 38 iphone properties objective-c key-value-coding

我想测试一个对象在iPhone SDK中是否有可写的@property.

一种可行的方法是检查-valueForKey:方法,但这似乎相当不优雅!

例:

  @try {
    id *value = [instance valueForKey:@"myProperty"];
  }
  @catch (NSException * e) {
    // Key did not exist
  }
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法呢?

Jas*_*oco 55

如果要创建正在检查的对象,则可以覆盖valueForUndefinedKey:setValue:forUndefinedKey执行比引发异常更有用的操作.

另一方面,如果您试图在运行时内省您不了解的对象,则必须使用运行时方法来执行此操作.您可以使用Objective-C的运行时本身并调用要么class_copyPropertyList或者protocol_copyPropertyList和处理这些,或者使用基金会,并调用respondsToSelector该对象上的KVC吸气给定属性/ setter方法,例如,一个属性foo只需要调用类似[someObject respondsToSelector:NSSelectorFromString(@"foo")];.


Bar*_*ark 5

通常,无法确定对象是否具有给定键的值.实例可能决定从其-valueForUndefinedKey:方法返回其他未定义键的值.或者它可能让默认实现抛出异常.现代Objective-C(2.0)对象通常在其公共API中声明相关属性.对于这些对象,您可以使用Objective-C运行时class_copyPropertyListprotocol_copyPropertyList获取可用属性的列表.您还可以模拟KVC搜索列表,通过repondsToSelector:实例响应适当的getter方法进行测试.最后,您可以使用运行时class_copyIvarList检查ivars以获取适当的ivar.这是你不应该做很多工作.它不能保证您在发送消息时知道对象实例是否会引发异常并且它表示更大的问题...valueForKey:

如果您有一组对象必须都为给定键提供值,但有些对象没有,那么您就遇到了设计问题.您应该定义一个@protocol声明所需属性的适当接口(在Objective-C中).然后,您可以测试是否符合此协议,或者使用编译器对您进行一些编译时类型检查,以确保实例符合协议(如果您传递单个实例).

  • 如果您控制有问题的类,因此知道类*将*响应包含您的属性的库版本中的适当选择器,请使用`respondsToSelector:`.在这种情况下,您应该直接使用getter方法而不是`valueForKey:`,因为它会更快. (3认同)