01.02.2014 Views

Objective-C Fundamentals

Objective-C Fundamentals

Objective-C Fundamentals

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

How messaging works<br />

169<br />

8.3.2 Handling unknown selectors<br />

Because method binding occurs at runtime, it’s possible for an object to receive a message<br />

to which it doesn’t know how to respond. This situation is an error, but before<br />

announcing the error, the runtime system gives the receiving object a second chance to<br />

handle the message. The process is commonly called message forwarding and can be used<br />

to easily implement certain design patterns such as the Decorator or Proxy patterns.<br />

When <strong>Objective</strong>-C can’t determine via class metadata which method to invoke for a<br />

message selector, it first checks to see if the class wants the entire message sent<br />

unchanged to another object. It attempts to invoke the forwardingTargetForSelector:<br />

message, which could be implemented by a class as follows:<br />

- (id)forwardingTargetForSelector:(SEL)sel {<br />

return anotherObject;<br />

}<br />

With this implementation, any unknown message sent to the object is redirected, or<br />

forwarded, to the object represented by anotherObject. This makes the original<br />

object appear from the outside as though it combined the features of both objects.<br />

Obviously the implementation of forwardingTargetForSelector: could become<br />

more complex. As an example, you could dynamically return different objects on the<br />

basis of the particular method selector passed in as an argument.<br />

forwardingTargetForSelector: is commonly called the “fast-forwarding path,”<br />

because it quickly and easily causes a message to be forwarded to another object without<br />

requiring too much code to be developed (or executed during runtime). It does have<br />

limitations, however: for instance, it isn’t possible to “rewrite” a message send to redirect<br />

a message addressed to one selector to be processed by another; nor is it possible to<br />

“drop” a message and ignore it. Fortunately, a “normal forwarding path” goes into<br />

action whenever the fast path doesn’t provide a suitable implementation for a missing<br />

method selector, and this feature provides more flexibility in how a message is handled.<br />

If forwardingTargetForSelector: isn’t implemented or fails to find a suitable target<br />

object (it returns nil), the runtime, before announcing an error, sends the object<br />

a forwardInvocation: message with an NSInvocation object as its sole argument.<br />

An NSInvocation object encapsulates the message being sent. It contains details<br />

about the target, selector, and all arguments specified in a message send and allows<br />

full control over the return value.<br />

Because your implementation of forwardInvocation: has full access to the<br />

NSInvocation object, it can inspect the selector and arguments, modify them, and potentially<br />

replace them, leading to a wide range of possibilities for altering the behavior.<br />

NSObject’s default implementation of forwardInvocation<br />

Every object that inherits from NSObject has a default implementation of the forwardInvocation:<br />

message. But NSObject’s version of the method invokes<br />

doesNotRecognizeSelector:, which logs an error message.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!