Search

Inside the Bracket, part 4 – Welcome to the Machine

Mark Dalrymple

14 min read

Jun 27, 2013

Inside the Bracket, part 4 – Welcome to the Machine

Want to learn more about what’s really happening inside those square brackets? Read the entire Inside the Bracket series.

Thar Be Errors In Them Hills

Error handling is one of the more interesting, and crucial, parts of designing software that others use. Errors can come from the system (hey! my disk is full!) or from the programmer (hey! String! Take your square root!). How do you report the error happened, and do you give the programmer an opportunity to recover?

Most forms of error handling let the programmer decide what to do next. You check the read() system call’s return value. If it’s -1 you go check errno and see what happened. You might get EINTR which tells you to go back and try the read again. You might get EBADF which tells you to just give up.

You can check the return values from Cocoa calls and then poke into an NSError object (remember not to check the NSError directly) Calls can throw exceptions which can be caught and an operation tried again. Occasionally you hit something, like an assert, that just kills your program outright with no recourse. Unless it’s something non-fatal, you usually have a chance to recover.

The Objective-C runtime is no different.

Lack Of Recognition

It’s like that friend who never leaves. You saw it in the last part.

This:

-[__NSCFNumber uppercaseString]: unrecognized selector sent to instance 0x17c3

There’s nothing preventing you from sending any message to any object.There’s no guarantee that the receiver actually handles the message. If the object can’t handle the message, Cocoa tries a bunch of stuff, and if that doesn’t work it gives up and prints out that Message of Doom.

-doesNotRecognizeSelector: is sent to the receiver when the message dispatch machinery can’t find a method in the piles of code that the involved classes have. The default implementation just throws an exception, which is Cocoa’s gesture of “the programmer screwed up somewhere”. Xcode’s Exception Breakpoints make it easy to tell Xcode to halt execution when an exception is thrown. Just go to the Breakpoint Navigator, click the Plus button, and choose Add Exception Breakpoint. Chuck a bad message at an object and it’ll bubble up to -doesNotRecognizeSelector: that throws the exception. The breakpoint will stop, letting you look at the stack trace. You should find the offending code a couple of frames down in the stack.

This breakpoint can be maddening if you’re in an exception-chatty environment, but you can still track down bad messages sends to a particular object by implementing an empty -doesNotRecognizeSelector: and putting a breakpoint on it. You can also consume did-not-finditude by implementing this method or by wrapping the offending message send in a @try/@catch. If you do stuff like that outside of debugging, it’s likely a sign that you’re masking some problem that should really be dealt with.`

You’re allowed to not-recognize things yourself, if you want. Why would you want to? To duplicate C++ abstract base classes. An abstract base class is a C++ idiom. You create one by declaring a virtual member function and assigning it to zero:

class AbstractBaseClass {
  public:
    virtual void overrideMe (int shoeSize) = 0;
};

This tells the compiler “don’t let anybody instantiate this class, or any subclass that doesn’t implement all of the = 0 virtual functions” Clang++ gives you nice errors for that, even telling you which methods need implementing:

abstrace.cpp:10:23: error: variable type 'AbstractBaseClass' is an abstract class
    AbstractBaseClass ook;
                      ^
abstrace.cpp:6:18: note: unimplemented pure virtual method 'overrideMe' in
      'AbstractBaseClass'
    virtual void overrideMe (int shoeSize) = 0;
                 ^

You use a construct like this to list a set of methods that only make sense for the user of the class to implement and your class is useless unless those methods are filled in. The compiler is enforcing an API contract.

You can’t do the same thing in Cocoa. There is no way for the compiler to unequivocally force the programmer to implement a set of methods. You can do the next best(?) thing by having things blow up at runtime. An equivalent Cocoa class would look like

@interface AbstractCocoaClass : NSObject
- (void) overrideMe: (NSInteger) shoeSize;
@end

The user of this class doesn’t know that overrideMe must be overridden. OK, maybe you could comment, but who actually looks at headers these days? As the implementor, you could just not implement it all and let the message dispatch machinery gripe about the unrecognized selector error at runtime. You’ll have to deal with the compiler warning when you didn’t implement all the public methods of the class. And we all know that Warnings Are Bad, mmmmkay?

You can use -doesNotRecognizeSelector: yourself! You could log an informative message, and then blow up at runtime:

- (void) overrideMe: (NSInteger) shoeSize {
    NSLog (@"You need to override -overrideMe: for proper function kthxbai");
    [self doesNotRecognizeSelector: _cmd];
} // overrideMe

Now, before you get all bondage-and-discipline on us, please ponder whether you really should do this. Yes, there are some cases where a class is completely unusable unless the programmer puts in some of their special mojo. We already have some nice patterns for that, such as @protocols, data sources and delegates. These allow customizability without subclassing.

Even if you think that subclassing your abstract base class is the right thing, make sure that you’re not putting an unnecessary burden the programmer. You want to have ten abstract methods, but will the programmer really have to override all ten methods every time? Will they be creating a pile of do-nothing methods? Back in the old days, you sometimes had to adopt NSInputServiceProvider. This is a protocol of fifteen required methods but you’d end up implementing two. But because it was a protocol, and all fifteen are required, you had a bunch of do-nothing empty methods. Ugly.

I prefer to use the existing Cocoa patterns like delegates. Otherwise, if there are methods that exist just to be overridden, I make empty bodies in the base class. I figure the programmer-in-the-future using this class may be using it in ways I didn’t expect, and so a runtime explosion (and even a log message) imposes unnecessary work on them. </soapbox>

Having some Fun

It’s nice having a sane way to handle errors. It’s even nicer when the toolkit gives us some toys to play with before the error is declared an error. An object might not have a method that implements -wombatDance:, but we can use some tools that make the object appear that it implements that method.

Before sending -doesNotRecognizeSelector: the message dispatch machinery sees if the receiving object has implemented -forwardInvocation:. It’s called if it exists. This method takes an NSInvocation as an argument, and returns nothing. As you saw time-before-last, NSInvocation is a freeze-dried message send. Your -forwardInvocation: can poke around that invocation, look at its selector and arguments, and decide what to do. You can even change the target and send it on to another object if you want. (hence the “forward” in the name).

You may be thinking, “An NSInvocation is involved, will this be slow?”. Why yes it is. NSInvocations are slower than regular message sends, and if you’re messing around with this kind of stuff, you’ll want to look at -forwardingTargetForSelector: covered later on..

Mucking Around

Let’s see if we can hook into this mechanism. Let’s do something really dumb, like declare a method, but don’t implement it, and still have it do something if the object is sent a message. The code can be found at this gist.

Here’s a category on NSObject that declares -wombatDance: so there won’t be any warnings if you send this message to random classes.

@interface NSObject (AllThingsCanDance)
- (void) wombatDance: (int) repetitions;
@end

Next is a Marsupial class that doesn’t do much:

@interface Marsupial : NSObject
@end // Marsupial

@implementation Marsupial
@end // Marsupial

And finally, we tell one of these dudes to do the wombat dance:

int main (void) {
    Marsupial *pouchy = [Marsupial new];
    [pouchy wombatDance: 23];
    return 0;
} // main

Complete surprise, you get an unrecognized selector message. Now time to subvert the system.

Before the machinery can send you an invocation, it need to know how to construct an invocation. What does it need to do that? A method signature. That means you need to override -methodSignatureForSelector: to return an appropriate signature. Almost all the time you’ll look up method signatures using a convenience method. For this, let’s go hardcore and make our own. Sometimes you might not be able to use a convenience method because a method doesn’t exist in a class, so it has nothing to look up when using +instanceMethodSignatureForSelector:, or you’ll get an infinite recursion if you call -methodSignatureForSelector: on self inside of -methodSignatureForSelector: (which I totally did not just do while writing this code.)

There’s a spiffy class method on NSMethodSelector called +signatureWithObjCTypes:. It takes a C string of @encodes like you saw in part 2. You could hard-code a list of the identifiers:

signature = [NSMethodSignature signatureWithObjCTypes: "v@:i"];

They’re ordered:

  • v – void, the return type

  • @ – id, self

  • : – selector, _cmd

  • i – int, the number of repetitions of the wombat dance

Yep, you still have to account for self and the selector arguments.

I’m kind of paranoid, so I like to construct these at run time by pasting together different @encode results into a string and feeding that to +signatureWithObjCTypes:. The encoding strings really haven’t changed in decades (and probably will never change), but given the accelerated pace the LLVM team is mutating Objective-C, I think it’s good to be paranoid.

@encodes generate C-style strings. You can paste together a bunch of C strings using the printf family. Rather than hardcoding a buffer size, I use asprintf. It dynamically allocates a chunk of memory to hold the final string.

This implementation of -methodSignatureForSelector: examines the selector. If it’s wombatDance: selector, a format string is built and fed into +signatureWithObjCTypes:, otherwise it’s sent up to the superclass for handling, which usually means death:

- (NSMethodSignature *) methodSignatureForSelector: (SEL) selector {
    NSMethodSignature *signature;
    if (selector == @selector(wombatDance:)) {
        char *typeEncodings;
        asprintf(&typeEncodings, "%s%s%s%s",
                 @encode(void),     // return
                 @encode(id),       // self
                 @encode(SEL),      // _cmd
                 @encode(int));     // repetitions
        signature =
            [NSMethodSignature signatureWithObjCTypes: typeEncodings];
        free (typeEncodings);
    } else {
        signature = [super methodSignatureForSelector: selector];
    }
    if (signature == nil) {
        NSLog (@"no signature for %@", NSStringFromSelector(selector));
    }
    return signature;
} // methodSignatureForSelector

Now when a Marsupial receives -wombatDance: the machinery knows what arguments it takes and the return value. That information will get packaged up, along with the value 23 for the iterations, and sent to -forwardInvocation:

- (void) forwardInvocation: (NSInvocation *) invocation {
    if (invocation.selector == @selector(wombatDance:)) {
        NSInteger repetitions = 0;
        [invocation getArgument: &repetitions  atIndex: 2];
        NSLog (@"You spin me right round baby right round %ld times", repetitions);
    } else {
        [super forwardInvocation: invocation];
    }
} // forwardInvocation

?
And when run, the call to -wombatDance: prints out:

% ./marsupial
You spin me right round baby right round 23 times

Oh yeah. We’ve subverted the system. That that Mister Man.

What about return values? Can you do this with a method that has a return value? After all, -forwardInvocation: returns nothing. You arrange for the invocation to have a return value, whether invoking the inovcation or setting ther return value directly. Once -forwardInvocation: returns, the return value will be delivered to the caller.

Multiple Inherifakes

What could you use this for? One use of forwarding is to make one object behave as if it were several different kinds of objects. Maybe it’s a façade – one object holds on to a half dozen different objects and forwards messages on to the appropriate contained object. You can think of it as a form of multiple inheritance. True multiple inheritance only exists in a few languages. C++ is one of them, and Objective-C is not, so we’d have to fake it.

Remember Calculus where the professor shows you the complete round-about way of doing something, assigns five hundred tedious problems, and then you get shown the “and oh by the way, here’s the trivial way to solve these”? I’m totally going there.

What does “real” multiple inheritance looks like in C++? Here’s two classes, each contributing one member function. The code for this can be found at the top of this gist.

class StringyThing {
  public:
    int length (void) { return 4; };
};
class NumberyThing {
  public:
    int intValue (void) { return 23; };
};

Then there’s one that inherits from both:

class CheesyThing : public StringyThing,
                    public NumberyThing {
};

CheesyThing objects are both StringyThings and NumberyThings. You can say a CheesyThing is-a StringyThing, and is-a NumberyThing, and has the full rights, privileges, member variables and member functions thereof:

CheesyThing cheddar;
printf ("It's not easy being cheesy: %d %dn",
        cheddar.length(), cheddar.intValue());

You can make some nice “mix-in” architectures with multiple inheritance (like the old PowerPlant framework). Unfortunately it has issues like the dreaded diamond problem.

Cover Story

So, what about Objective-C? You can’t have one object directly inheriting from two classes. There’s only one isa pointer in our class structure, after all. There are ways you can fake it. One way is to expose the different “subclasses” as @protocols (a.k.a. “interface inheritance”) – you have your über object adopt those protocols, and then write cover methods.

Here’s two protocols:

@protocol XXStringy
- (NSUInteger) length;
@end
@protocol XXNumbery
- (NSInteger) intValue;
@end

And a class that “multiply inherits”:

@interface XXCheesyThing : NSObject  {
    NSString *_string;
    NSNumber *_number;
}
@end // XXCheesyThing

Remember that adopting a protocol does not bring along any implementation like it does over in C++ land.

Populate the instance variables:

-- (id) init {
    if ((self = [super init])) {
        _number = @( 23.42 );
        _string = @"Bork";
    }
    return self;
}

And implement the cover methods:

- (NSInteger) integerValue {
    return _number.integerValue;
}
- (NSUInteger) length {
    return _string.length;
}

They just turn around and sort of forward the message along the way to the correct object (you can see where this is eventually going). You can use these calls without incident:

XXCheesyThing *chedzor = [XXCheesyThing new];
printf ("L33T CH3DZ()RZ: %ld %ldn",
        chedzor.length, chedzor.intValue);

Sure enough, it works:

% clang++ -DCOVER_METHODS=1 -fobjc-arc -g -ObjC++ -Wall -framework Foundation -o machinery machinery.cpp
% ./machinery
It's not easy being cheesy++: 23 4
L33T CH3DZ()RZ: 23 4

Automatic Forwardification

There’s two big problems. The first is cover method proliferation: a couple of complicated protocols could turn into a whole bunch of one-line cover methods. If you’re doing pass-throughs to contained objects (such as exposing all of NSString’s API), you’ll have a whole lot of cover methods. The second problem is that it is brittle. Say the XXStringy protocol is extended to add a couple of new methods. You will either have to tweak XXCheesyThing to add the cover methods (bye-bye open/closed principle), or risk getting unrecognized selector errors at runtime.

Wouldn’t It Be Nice to automate that process? You can implement -methodSignatureForSelector: and -forwardInvocation: and use those to send messages on to the contained object. Given the selector, see if the XXCheesyThing or a superclass knows about it, otherwise query the embedded objects:

- (NSMethodSignature *) methodSignatureForSelector: (SEL) selector {
    NSMethodSignature* signature;
    signature = [super methodSignatureForSelector: selector];
    if (signature) return signature;
    signature = [_number methodSignatureForSelector: selector];
    if (signature) return signature;
    signature = [_string methodSignatureForSelector: selector];
    if (signature) return signature;
    NSLog (@"could not find signature for selector %@",
           NSStringFromSelector(selector));
    return NULL;
} // methodSignatureForSelector

That gives the machinery the information it needs to construct the invocation. Inside of -forwardInvocation:, ask each embedded object what it responds to:

- (void) forwardInvocation: (NSInvocation *) invocation {
    if ([_number respondsToSelector: invocation.selector]) {
        [invocation invokeWithTarget: _number];
    } else if ([_string respondsToSelector: invocation.selector]) {
        [invocation invokeWithTarget: _string];
    } else {
        [super forwardInvocation: invocation];
    }
} // forwardInvocation

There are a couple of unfortunate tweaks that need to be made to the rest of the code, though. The compiler is stricter now than it was in the early days of Cocoa and Objective-C. Things that we could do then now turn into errors and warnings. If we adopt protocols we need to implement those methods or else live with warnings in our implementation. This could be a valid engineering decision. Back in the day we’d use informal protocols (categories on NSObject) add methods to every object. So do that now:

@interface NSObject (XXNumbery)
- (NSInteger) integerValue;
@end
@interface NSObject (XXStringy)
- (NSUInteger) length;
@end

With this in place, you can send these messages to XXCheesyThing objects without the compiler complaining. Granted, we can now send these messages to NSPropertyListSerialization as well and have things blow up at runtime. We’ve traded some compiler checking for convenience.?
This does simplify the XXCheesyThing declaration – no protocols:

@interface XXCheesyThing : NSObject {
    NSNumber *_number;
    NSString *_string;
}
@end // XXCheesyThing

One side effect to those “ask the interior objects if they respond to selector” implementation is that not only do the previous calls still work:

NSLog (@"L33T CH3DZ()RZ: %ld %ldn",
       [chedzor integerValue], [chedzor length]);

But you can send any message that NSString or NSNumber responds to:

NSLog (@"    others: %.2f, %@",
       [chedzor floatValue], [chedzor uppercaseString]);

This will print out:

L33T CH3DZ()RZ: 23 4
others: 23.42, BORK

-uppercaseString bounces off of XXCheesyThing, falls into forwardSelector, the embedded string happily consumes it, and it returns an uppercase string.

Whether this is awesome or terrifying is up to you. It’s awfully convenient – just forward things around. It also leads to fuzzy, surprising interfaces. Just by looking at XXCheesyThing, you wouldn’t expect it to respond to -uppercaseString.

So, while this is a cool technique, it isn’t terribly useful as a general form of multiple inheritance. You use informal protocols (which are now passé), implement stub methods, or live with/suppress warnings. If you’re thinking “Hey, I need to treat these two objects as one!”, be sure to ponder the consequences. Even better, write little test programs that tries wrapping them together in different ways see if works for you.

Where it can come in handy are where you’re dealing with objects very abstractly, just via ID. You could have an array full of homogenous objects. A loop spins through the array and sends -integerValue to each object. The loop doesn’t care if the object in the array is an NSNumber, or an NSNumber wrapped in an XXCheesyThing, or some other thing that responds to -integerValue. Similarly, with NSTableView, you can use the identifier of the table column as the selector of a message to send to an object to provide the cell data. This object could use embedded objects and forwarding to do its work. Because it’s treated as an id by the tableview classes, you don’t have to worry about babysitting the compiler as much.

Finally, if you are wanting to use forwarding to do your own form of multiple inheritance, you’ll want to override -respondsToSelector: so that you can say “yes, I support -length and -integerValue!”, and perhaps also -isKindOfClass so the object could be used transparently as an NSString and an NSNumber.

Sleight of Hand

I must admit to a little cheating. You’ll notice that the Numbery things always precede the Stringy things in the code. This is intentional, which shows another sharp corner. Both NSString and NSNumber respond to -integerValue. If the two forwarding methods had checked the string first, the string would have received all the messages and the output wouldn’t have matched the C++.

Quicker Picker Upper

One more thing before wrapping up this session. If you decide to use forwarding for something cool and froopy you will want to use the faster mechanism that uses -forwardingTargetForSelector:. Rather than mucking around with invocations, peering inside of them, maybe digging out arguments, you just override this method and return the object that should handle the message. The returned object then gets sent the message (and then its forwarding mechanisms might kick in, like turtles all the way down). No need to implement -methodSignatureForSelector: because there’s no invocation involved. (Thank you to all my calculus teachers for this pedagogical technique.):

- (id) forwardingTargetForSelector: (SEL) selector {
    if ([_number respondsToSelector: selector]) {
        return _number;
    } else if ([_string respondsToSelector: selector]) {
        return _string;
    } else {
        return [super forwardingTargetForSelector: selector];
    }
} // forwardingTargetForSelector

Coming Up

Next time : Mayhem.

Mark Dalrymple

Author Big Nerd Ranch

MarkD is a long-time Unix and Mac developer, having worked at AOL, Google, and several start-ups over the years.  He’s the author of Advanced Mac OS X Programming: The Big Nerd Ranch Guide, over 100 blog posts for Big Nerd Ranch, and an occasional speaker at conferences. Believing in the power of community, he’s a co-founder of CocoaHeads, an international Mac and iPhone meetup, and runs the Pittsburgh PA chapter. In his spare time, he plays orchestral and swing band music.

Speak with a Nerd

Schedule a call today! Our team of Nerds are ready to help

Let's Talk

Related Posts

We are ready to discuss your needs.

Not applicable? Click here to schedule a call.

Stay in Touch WITH Big Nerd Ranch News