0

I have a strange task. I need to get an array that contains all the functions in an objective c object. I then need to be able to tell if each function is a class method or not. Then I need to get the names (preferably an NSString) of each parameter and the type each parameter takes. Is there a way to do this? If not, does anyone know how to access the keys and values coded in the NSCoding Protocol function -(void)encodeWithCoder:(NSCoder*)aCoder; without using NSKeyedArchiver? What I am trying to do here is display a list of properties required to initialize an object. All my objects use class methods to initialize themselves. I am making a level editor that allows me to edit properties that differ between objects and I don't feel like writing getPropertyList and initWithProperties functions for every single object since I have already done this by implementing the NSCoding protocol.

Ben Trapani
  • 271
  • 1
  • 4
  • 11
  • 2
    There are lots of "introspection" functions in the [Objective-C Runtime Reference](http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html). Figuring out how to use them is an exercise for the student, however. – Hot Licks May 14 '12 at 01:32

1 Answers1

2

I need to get an array that contains all the functions in an objective c object. I then need to be able to tell if each function is a class method or not.

Easy enough: you want class_copyMethodList(), which gets you just the instance methods for that class. To get the class methods, pass the class object, e.g. class_copyMethodList(object_getClass([NSString class]), &count);

Then I need to get the names (preferably an NSString) of each parameter and the type each parameter takes.

The parameter name part is probably not possible. They're not included in the method's metadata, and I'm pretty sure that they don't survive compilation at all; digging them out of the executable if they're there would certainly not be easy.

The types, however, are easily accessible via one of two runtime functions: either method_getTypeEncoding(), which gets you the signature string for the method's return and arguments, or method_getArgumentType(), which will let you loop over the argument types (the returned strings use the same code as the full type string).

If not, does anyone know how to access the keys and values coded in the NSCoding Protocol function -(void)encodeWithCoder:(NSCoder*)aCoder without using NSKeyedArchiver?

Are you talking about the particular implementation that you've made for encodeWithCoder:? You want the list of ivars implied by [coder encodeObject:firstIvar forKey:@"firstIvar"]; [coder encodeObject:secondIvar forKey:@"secondIvar"];? I'm not sure what that has to do with method signatures, but if so, you could make an NSCoder subclass that creates a dictionary from when you pass it as the coder and send encodeWithCoder: to your objects (see this answer I posted the other day).

What I am trying to do here is display a list of properties required to initialize an object.

What about a class method that returns an array with the names of the properties?

+ (NSArray *)essentialPropertyNames {
    return [NSArray arrayWithObjects:@"firstIvar", @"secondIvar", nil];
}

That would probably be less effort than picking through the runtime/class metadata and wouldn't be any less odd.

All my objects use class methods to initialize themselves.

That sounds unusual at best. In Cocoa, instances should use some form of -init to do their initialization.

Community
  • 1
  • 1
jscs
  • 63,694
  • 13
  • 151
  • 195
  • The parameter names could be inferred from the selector which can be accessed using `method_getName()`. Also `[NSString class]` returns a `Class` type, `object_getClass()` expects an `id` parameter. The call to object_getClass() is unnecessary. – mttrb May 14 '12 at 03:28
  • I'd say "guessed" rather than "inferred" (since they can really be anything at all), but that's a good point. – jscs May 14 '12 at 03:29
  • Yeah, it certainly wouldn't be perfect but I believe it is the best available. – mttrb May 14 '12 at 03:37
  • Thanks that solved my problem. I can determine parameter names from the type each one wants. Don't worry about the NSCoding thing. – Ben Trapani May 14 '12 at 10:47
  • @mttrb: Missed the last part of your comment earlier. You have to use `object_getClass()` to get the meta-class object, whose "instance methods" are the class methods of the original class. A `Class` is also an object and can be put into an `id` variable. – jscs May 14 '12 at 17:24
  • Interesting, I'll have to have a play with that. You learn something new everyday :) – mttrb May 15 '12 at 01:44