5

Looking only at the Objective-C runtime library, when a message is sent to an object that doesn't respond to it, the runtime system gives the receiver another chance to handle the message. So, the receiver's forward:: method, if implemented, gets called. However, looking at NSObject.mm, NSObject doesn't seem to implement forward::.

So, how does NSObject's forwardInvocation: method gets called, since the only thing the runtime system calls when a forwarding is needed is forward::? Does Foundation use objc_setForwardHandler (runtime.h) to set a new handler that calls forwardInvocation: whenever a message sent to a NSObject object needs to be forwarded?

LuisABOL
  • 2,951
  • 4
  • 25
  • 57

2 Answers2

12

At some point way back in time, there was no NSObject in the Objective-C runtime. When the language was first created by Brad Cox and Tom Love they added in a root object class, called Object. This implemented [Object forward::] , which was used to do message forwarding.

A few years later, NextStep came along and made their own additions to the language, creating the OpenStep framework (which became Cocoa). NextStep got rid of the Object class, and replaced it with NSObject. One of the changes that was made was to replace the forward:: method with forwardInvocation. The Object class is still kicking around in the source code (as you have found), but I'm pretty sure it's not available in either iOS or 64 bit OS X apps.

You are correct to suggest that objc_setForwardHandler is used to indicate that forwardInvocation should be used instead of forward:: for all NSObjects. I am afraid I'm not sure when Foundation calls this...I would guess at NSObject initialisation. I am also not massively up on the underlying runtime implementation, but hopefully that will have been of at least some help?

lxt
  • 31,146
  • 5
  • 78
  • 83
  • According to an Apple mailing list post from about six years ago ([link here](http://lists.apple.com/archives/objc-language/2007/Oct/msg00036.html)) you can't use `objc_setForwardHandler` unless you're running without foundation. The thread I linked to might have more information that could help you. – lxt Mar 02 '13 at 20:45
  • Yes, it helped me. Now I'm sure `Foundation` calls `objc_setForwardHandler` to make `forwardInvocation` get called. If I call `objc_setForwardHandler(NULL, NULL)`, what would override any previously set forward handler, the `forward::` method of my class is called, instead of `forwardInvocation`. So, most surely, on startup, Foundation calls `objc_setForwardHandler` passing `forwardInvocation`'s IMP as arguments. – LuisABOL Mar 02 '13 at 20:46
  • You would assume so. I know that the `Cocotron` open source implementation of `Foundation` does it on `NSObject` initialization ([source here](http://cocotron.googlecode.com/svn/trunk/Foundation/NSObject/NSObject.m)). – lxt Mar 02 '13 at 20:49
  • Setting a breakpoint on `objc_setForwardHandler` shows that it is called from `__CFInitialize` in the CoreFoundation library. – Martin R Mar 02 '13 at 23:12
  • "but I'm pretty sure it's not available in either iOS or 64 bit OS X apps" What do you mean "not available"? – user102008 Mar 04 '13 at 06:38
  • @user102008 - it's not included in Foundation or the run-time. GCC also deprecated it and removed any useful methods from their implementation in 2011. If you try and use `Object` when targeting iOS or 64-bit OS X you'll get an error, and XCode will re-direct you to the `NSObject` documentation. – lxt Mar 04 '13 at 09:04
1

This SO post has a more detailed answer to your question as to what happen when a message is sent to an object that doesn't respond to it.

Community
  • 1
  • 1
Boon
  • 40,656
  • 60
  • 209
  • 315