I'm doing research about Objective-C, and I'd like to know if it has the concept of reflection. None of the documents I've found so far describes reflection.
There are runtime functions described in Runtime Reference which allows not only querying for features of a class or an instance, but also adding a method, or even creating a new class at runtime. I say this is a very dynamic kind of reflection, which was not usually available to C-based languages. Mike Ash's wrappers is an Objective-C wrapper around that. Again, it can even add methods! The base class of Cocoa, NSObject
, also provide wrappers for many of the runtime functions, see NSObject
protocol reference. For example
[foo respondsToSelector:@selector(bar:)];
if([foo isKindOfClass:[NSString class]]){ ... }
does what the method names say. You can even add a method on the fly. For example,
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface Foo:NSObject
{
}
@end
@implementation Foo
-(void)sayHi
{
NSLog(@"Hi! from %@",NSStringFromSelector(_cmd));
}
+(BOOL)resolveInstanceMethod:(SEL)sel
{
Method method=class_getInstanceMethod(self,@selector(sayHi));
class_addMethod(self,sel,method_getImplementation(method),method_getTypeEncoding(method));
return YES;
}
@end
int main(){
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc] init];
Foo* foo=[[Foo alloc] init];
[foo aeiou];
[foo bark];
[foo mew];
[pool drain];
return 0;
}
This produces the output
Hi! from aeiou
Hi! from bark
Hi! from mew
What it does is as follows:
SEL
is the variable which represents the sent message (or method call, in the other terminology.)resolveInstanceMethod:
of a class if a message sent to an instance is not implemented in the classsayHi
to that method's implementation._cmd
to see what was the selector used in calling the method. So, even from a single sayHi
implementation, we can get different output.Some of the standard Cocoa's implementation (Key-Value-Coding, Key-Value-Observing and Core Data in particular) uses the runtime to dynamically modify the class.