How Introspection Works in iOS Apps
Introspection refers to facilities in an iOS apps’ programming language to examine the structure and other details of an object and its class at runtime. Such details can include:
An object’s inheritance tree
Whether it conforms to a specific protocol
Whether it responds to a certain message
When you know what an object is made of, you can programmatically construct messages to send to it, which makes your program much more dynamic.
How to get the class of an object
You can get the class of an object at runtime. In fact, Objective-C treats classes as first-class objects. Every class object points to a data structure in memory, has a superclass (known as a metaclass), and can respond to messages that invoke methods.
When you call a class method, you’re really sending a message to the object of the class.
You can get a reference to the class object for the class by sending the class a class message (Boy! Was that confusing to write.), and you get the superclass of a class by sending the object a superclass message. For example, you can print the class and the superclass of an object, such as a StackOfInteger object, as follows:
StackOfInteger *aStack = [[StackOfInteger alloc] init]; NSLog(@"Class is %@, and super is %@.",[aStack class],[aStack superclass]);
How to dynamically call methods
You can then call a method on a class object like this:
Class postfixCalculatorClass = [someObject class]; [postfixCalculatorClass performSelector:@selector(printClassDescription)];
Two items need to be explained here. First, the @selector is a compile-time directive and returns a pointer to the method printClass. Second, you can then use performSelector to actually call that method.
In the previous example, the method name was translated to a pointer to the method at compile time. You can also call an instance method on an object by using the string name of a method, at runtime, as follows:
SEL printClassDescriptionSEL = NSSelectorFromString(@"printClassDescription"); [postfixCalculatorClass performSelector:printClassDescriptionSEL];
In this example, you can use the SEL type (also known as a selector in Objective-C parlance, and so the SEL) to hold the internal representation of a method.
How to check the specification of an object
Once you have a handle to a class object, you can inspect it at runtime using the introspection functions provided in Objective-C. For example, you can test this object to see what kind it is. You can inspect it to see if it has a certain method or a certain attribute, and so on.
The table below shows all the methods for testing the structure and capabilities of a class object and for performing actions on it.
|Method||Question or Action|
|-(BOOL) isKindOf: class-object||Is the object a member or descendant of a class?|
|-(BOOL) isMemberOf: class-object||Is the object a member of a class?|
|-(BOOL) respondsTo: selector||Can the object respond to a method?|
|+(BOOL) instancesRespondTo: selector||Can instances of the class respond to a message?|
|-(id) perform: selector||Apply the method specified by selector.|
|+(BOOL) conformsToProtocol: (Protocol *)aProtocol||YES if the receiver conforms to the protocol aProtocol; otherwise, NO.|
For more details on introspection and how to use it, check out the Apple iOS Runtime Reference and the Apple Developer Objective-C Runtime Programming Guide.