objective-creflection

Does Objective-C have reflection?


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.


Solution

  • 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:

    1. SEL is the variable which represents the sent message (or method call, in the other terminology.)
    2. Objective-C runtime calls resolveInstanceMethod: of a class if a message sent to an instance is not implemented in the class
    3. So, in this case, I just copy an implementation of a predefined method called sayHi to that method's implementation.
    4. From the method, you can use _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.