如何使用键值编码判断对象是否存在键?
我想测试iPhone SDK中的对象是否具有可写的@property。
一种可能的方法是检查 -valueForKey: 方法,但这看起来相当不优雅!
示例:
@try {
id *value = [instance valueForKey:@"myProperty"];
}
@catch (NSException * e) {
// Key did not exist
}
有更好的方法吗?
I'd like to test whether an object has a writeable @property in the iPhone SDK.
One possible way of doing this is to check the -valueForKey: method, but that seems rather inelegant!
Example:
@try {
id *value = [instance valueForKey:@"myProperty"];
}
@catch (NSException * e) {
// Key did not exist
}
Is there a better way of doing this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您正在创建正在检查的对象,则可以覆盖
valueForUndefinedKey:
和setValue:forUndefinedKey
来执行比引发异常更有用的操作。另一方面,如果您试图在运行时内省您不知道的对象,则必须使用运行时方法来执行此操作。您可以使用 Objective-C 运行时本身并调用
class_copyPropertyList
或protocol_copyPropertyList
并处理它们,或者使用 Foundation 并调用respondsToSelector
给定属性的 KVC getter/setter 对象,例如,对于属性foo
,您可以调用类似[someObject respondsToSelector:NSSelectorFromString(@"foo")];
。If you are creating the object that is being checked, you could override
valueForUndefinedKey:
andsetValue:forUndefinedKey
to do something more useful than raising an exception.If, on the other hand, you are trying to introspect objects you don't know about at runtime, you will have to use the runtime methods to do that. You can either use the objective-c runtime itself and call either
class_copyPropertyList
orprotocol_copyPropertyList
and deal with those, or use Foundation and callrespondsToSelector
on the object for the KVC getter/setters for a given property, e.g., for a propertyfoo
you would call something like[someObject respondsToSelector:NSSelectorFromString(@"foo")];
.一般来说,无法确定对象是否具有给定键的值。实例可能决定从其
-valueForUndefinedKey:
方法返回未定义键的值。或者它可能会让默认实现抛出异常。现代 Objective-C (2.0) 对象通常在其公共 API 中声明相关属性。对于这些对象,您可以使用 Objective-C 运行时的class_copyPropertyList
或protocol_copyPropertyList
来获取可用属性的列表。您还可以模拟 KVC 搜索列表,通过repondsToSelector:
测试实例是否响应适当的 getter 方法。最后,您可以使用运行时的class_copyIvarList
来检查 ivars 是否有合适的 ivar。这是很多您不应该做的工作。它不能保证您知道对象实例在发送valueForKey:
消息时是否会引发异常,并且它表明存在更大的问题...如果您有一个对象集合,它们必须全部提供一个给定键的值,但有些没有,您遇到了设计问题。您应该定义一个适当的接口(Objective-C 中的@protocol)来声明所需的属性。然后,您可以测试是否符合此协议,或者使用编译器为您执行一些编译时类型检查,以确保实例符合协议(如果您传递单个实例)。
There is no way, in general, to determine if an object has a value for a given key. An instance may decide to return a value for an otherwise undefined key from its
-valueForUndefinedKey:
method. Or it may let the default implementation throw an exception. Modern Objective-C (2.0) objects often declare relevant properties in their public API. For these objects, you can use the Objective-C runtime'sclass_copyPropertyList
orprotocol_copyPropertyList
to get a list of the available properties. You can also emulate the KVC search list, testing viarepondsToSelector:
if the instance responds to an appropriate getter method. Finally you could use the runtime'sclass_copyIvarList
to check the ivars for an appropriate ivar. This is a lot of work that you shouldn't be doing. It won't guarantee that you know whether an object instance will raise an exception when sent avalueForKey:
message and it indicates a bigger issue...If you have a collection of objects that must all provide a value for a given key, but some don't, you have a design problem. You should define an appropriate interface (a
@protocol
in Objective-C) that declares the needed properties. You can then test for conformance to this protocol, or make use of the compiler to do some compile-time type checking for you to make sure instance conform to the protocol (if you're passing around single instances).以下是@Jason Coco 的回答。
这是我提供的关于如何专门检查您要设置的属性的“设置”选择器是否存在的建议。
这纯粹是肮脏的东西,但它确实有效,而且我发现自己正在使用它。你已经被警告过..
用法:
快速:
然后将代码片段添加到桥接标头中:
Following on from @Jason Coco answer.
Here is my offering on how to check specifically for the "set" selectors existence of the property you're trying to set.
This is pure filth but it works and I've found myself using it. You've been warned..
Usage:
In swift:
Add the code snippet to your bridging header then:
您在问题中提出的 try/catch 方法是了解
valueForKey:
是否会引发异常的唯一可靠方法。The try/catch approach you propose in your question is the only reliable way of knowing whether
valueForKey:
will throw an exception.