0

I am new to objective C and from C/C++ background, I am trying hard to understand how much dynamic is objective C.

Programming with Objective-C Page 38

Consider the following code:

id someObject = @"Hello, World!";
[someObject removeAllObjects];

In this case, someObject will point to an NSString instance, but the compiler knows nothing about that instance beyond the fact that it’s some kind of object. The removeAllObjects message is defined by some Cocoa or Cocoa Touch objects (such as NSMutableArray) so the compiler doesn’t complain, even though this code would generate an exception at runtime because an NSString object can’t respond to removeAllObjects.

The removeAllObjects message is defined by some Cocoa or Cocoa Touch objects (such as NSMutableArray) so the compiler doesn’t complain.

Does that mean, run time will actually look for all the methods implemented? If yes, doesn't it affect performance?

Please suggest if my understanding is wrong.

Thanks.

Simon McLoughlin
  • 8,293
  • 5
  • 32
  • 56
Pranit Kothari
  • 9,721
  • 10
  • 61
  • 137
  • The true 'dynamicity' of objective-c comes when you start messing with the run-time functions to create, modify, and even remove existing classes, not just sending messages around. – Richard J. Ross III Apr 11 '14 at 08:17

1 Answers1

5

TheEye's answer is totally incorrect and I think it is important for those new to Objective-C to understand how it actually works.

There are no methods in Objective-C. You send messages to objects. That is not just a minor syntax difference, it's a fundamentally different philosophy.

What actually happens when you send the removeAllObjects message to an object (regardless of whether it is declared as id or NSString*), the runtime looks at the object's isa (is-a) pointer at runtime, which points to that object's definition.

Each object definition has a list of message selectors the object implements. For runtime performance, the system caches the selectors. So it will check to see if the cache already contains that selector. If it does, the runtime jumps to that location and begins executing the code found there. It will also check up the chain of inherited classes to see if any of them implement the message.

If it can't find the message, it will then send the selector to forwardInvocation:. That happens for all unknown messages. It just so happens that NSObject's default implementation of forwardInvocation: invokes doesNotRecognizeSelector: which will crash.

You can test this yourself by implementing forwardInvocation: on your own class and doing nothing. Then try sending random selectors to an instance of your class. You will see that no errors are raised. This allows you to create proxy objects that inspect, filter, or modify messages destined for another object. You can also impersonate a different class entirely.

The type of a variable declared in the code is only a hint so the compiler can help you catch errors at compile time. At runtime, it doesn't really matter. Objective-C only looks at the isa pointer to determine an object's class and thus what message selectors it supports.

That's also why you can override a class at runtime, add new methods to a class, etc. You can even change an object's type at runtime by changing the isa pointer, which will cause the bytes of that object to be re-interpreted as the new type (Warning: this is advanced stuff so please be careful!)

russbishop
  • 16,587
  • 7
  • 61
  • 74
  • 1
    Note that for certain objects (tagged pointers), the `isa` pointer simply doesn't exist, it is encoded inside the pointer itself, and is not a memory address at all. – Richard J. Ross III Apr 11 '14 at 10:15
  • Also note that impersonating a different class (using `class_poseAs`) can no longer be done with the current version of the runtime. – Richard J. Ross III Apr 11 '14 at 10:17
  • That's true, and non-pointer isa on arm64 is not strictly a pointer either, though it does contain a 30 bit offset to the class definition. I meant impersonating as in forwarding or proxy, you are correct that direct impersonation was removed. You can always tell a pointer from non-pointer because proper pointers are aligned, so the lowest bits will be zero. A tagged pointer or non-pointer isa will have bits set. – russbishop Apr 13 '14 at 03:44
  • One nit: there _are_ methods, it's just that the link between message and method is not absolute. Perhaps it would be better to say that there are no method _calls_. – jscs Apr 27 '14 at 19:26