macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Inside the Objective-C Runtime
Pages: 1, 2

If you want to know how many parameters a method expects, just count the colons in the selector. A selector (SEL) is a const char* (that has been uniqued) so you can use standard C string functions.



For a method with more than two parameters no methods are defined. Instead we need to invoke the underlying runtime function. It's easy. The function is objc_msgSend(), which is defined as:

    id objc_msgSend(id self, SEL op, ...);

So objc_msgSend() takes an object upon which a method should be invoked (a "target"), and a selector (or action) to perform, along with a variable number of arguments.

    #import <objc/objc-runtime.h>; // for objc_msgSend()
    SEL fiveArgumentSelector = @selector(aMethod:that:takes:five:arguments:);
    id result = objc_msgSend(myCustomInstace, fiveArgumentSelector,
		arg1, arg2, arg3, arg4, arg5);

An exception is raised if you "send" a message to an object which doesn't implement the corresponding method. Note we've #imported a new header. On Mac OS X you’ll find the ObjC headers in /usr/include/objc (on other systems, try: System/Developer/Headers/objc).

Related Reading

Learning Cocoa
By Apple Computer, Inc.

One of the many elegant and clever uses of dynamic binding is "delegates". Delegates are widely used in the AppKit, allowing you to effectively customize standard AppKit objects by intervening at decision points and thereby modifying behavior. Rather than registering a string of callbacks, you implement whichever delegate methods you want to catch (such as: -windowWillClose:).

Thanks to dynamic typing and dynamic binding, the implementation can be on ANY class. The cool thing here about the dynamism of ObjC is that you don't need to conform to a Protocol or otherwise implement all the delegate methods: each delegate method will be invoked only if it is implemented.

This works because we can query the runtime about which methods an object implements. Once again NSObject provides a convenient O-O interface to the runtime. Does an object implement a method? "Ask" the object:

	if ([aDelegate respondsTo:someSelector]) ...

Here's the declaration:

	- (BOOL)respondsToSelector:(SEL)aSelector;

Another feature of dynamic binding allows container objects (NSArray, NSDictionary, NSSet, etc.) to message their contained objects consistently, without requiring those objects to reside at a particular place in the inheritance hierarchy or adopt a formal Protocol. NSArray declares the following:

	- (void)makeObjectsPerformSelector:(SEL)aSelector;
	- (void)makeObjectsPerformSelector:(SEL)aSelector 
		withObject:(id)argument;

Which invokes -(id)performSelector:(SEL)aSelector and -(id)performSelector:(SEL)aSelector withObject:(id)object, respectively on each object contained by the NSArray. You can add another makeObjectsPerform... which takes 2 (or 3 or 4) arguments using a Category.

Categories

Categories are a feature of Objective-C that allows you to extend the functionality of ANY class. You don't need the source code of the class, no need to re-compile it either. Just declare a category, implement the method, and presto! All instances of the class or of any subclass now respond to your new methods. One usage of categories is to add convenience methods:

    @implementation NSString (NSString-Extensions)
	- (BOOL) containsString:(NSString *)aString;
	/*" Returns YES if the receiver contains aString, NO otherwise. "*/
	{ return ([self rangeOfString:aString].length != 0); }
    @end

But you can add any functionality you need. Sometimes it's the best way to get something done. At other times it's not and you may want to implement "helper" functions instead. For example:

    BOOL doesStringContainSubstring(NSString* string, NSString *substring)
    { return (string != nil && [string rangeOfString:substring].length != 0); }

With a Category you can add class or instance methods, but you can't add instance variables.

Another use of Categories is grouping functionality and coding responsibility in a group of developers. Putting category methods in separate source (.h and .m) files can be a useful way of organizing development of your own classes.

The MiscKit makes extensive use of categories and provides examples of good Category usage along with code you may want to use.

Overidding Behavior

Another thing categories let you do is override and customize behavior for existing methods. Although I've encountered times when this let me easily do things that would otherwise have been a lot of work, it is a feature that needs care. If you override a low-level method (a dispatch method on NSObject, for instance) this can have serious side effects. Such usage is generally NOT recommended. It's always a good idea to test your code thoroughly; overriding an object's methods in a category demands good testing.

Overriding a method in a category requires no special code, just declare and implement the method.

    @implementation NSObject (ObjectOverride)
    - description {
	return [NSString stringWithFormat:@"<objc-object>%@</objc-object>", [self class]];
    }
    @end

Note, as already mentioned, this is not recommended and usually leads to unwanted side effects. In cases like this, use categories to extend classes:

    @implementation NSObject (XMLDescription)
    - xmlDescription {
	return [NSString stringWithFormat:@"<objc-object>%@</objc-object>", [self class]];
    }
    @end

You're free to implement both instance and class methods in categories.

If you want more background on the Objective-C language and its features, an excellent resource is available on Apple's developer Web site at: http://developer.apple.com/techpubs/macosx/Cocoa/XObjC/XObjC.pdf

Final Thoughts

Now that you've begun your exploration of runtime, I hope you'll take a look at next week's article that digs deeper and looks at how it's implemented. Plus, you'll get a look at the runtime browser, which I think you'll find very useful. See you then!

Ezra Epstein is a long time Objective-C programmer who enjoys working on Mac OS X.


O'Reilly & Associates published Building Cocoa Applications: A Step By Step Guide by Michael Mahoney & Simson Garfinkel in May, 2002.

You can also look at the Full Description of the book.

For more information, or to order the book, click here.


Return to the Mac DevCenter.