How do you tell if a key exists for an object using Key-Value Coding?

If you are creating the object that is being checked, you could override valueForUndefinedKey: and setValue: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 or protocol_copyPropertyList and deal with those, or use Foundation and call respondsToSelector on the object for the KVC getter/setters for a given property, e.g., for a property foo you would call something like [someObject respondsToSelector:NSSelectorFromString(@"foo")];.


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's class_copyPropertyList or protocol_copyPropertyList to get a list of the available properties. You can also emulate the KVC search list, testing via repondsToSelector: if the instance responds to an appropriate getter method. Finally you could use the runtime's class_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 a valueForKey: 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).