Hidden features of Objective-C [closed]
Asked Answered
W

8

12

Objective-C is getting wider use due to its use by Apple for Mac OS X and iPhone development. What are some of your favourite "hidden" features of the Objective-C language?

  • One feature per answer.
  • Give an example and short description of the feature, not just a link to documentation.
  • Label the feature using a title as the first line.
Wolpert answered 17/10, 2008 at 10:6 Comment(1)
See meta.stackexchange.com/questions/56669/…, meta.stackexchange.com/questions/57226/…, and related Meta postsWendel
P
20

Method Swizzling

Basically, at runtime you can swap out one implementation of a method with another.

Here is a an explanation with code.

One clever use case is for lazy loading of a shared resource: usually you would implement a sharedFoo method by acquiring a lock, creating the foo if needed, getting its address, releasing the lock, then returning the foo. This ensures that the foo is only created once, but every subsequent access wastes time with a lock that isn't needed any more.

With method swizzling, you can do the same as before, except once the foo has been created, use swizzling to swap out the initial implementation of sharedFoo with a second one that does no checks and simply returns the foo that we now know has been created!

Of course, method swizzling can get you into trouble, and there may be situations where the above example is a bad idea, but hey... that's why it's a hidden feature.

Pucker answered 17/10, 2008 at 10:6 Comment(0)
R
16

Posing

Objective-C permits a class to entirely replace another class within an application. The replacing class is said to "pose as" the target class. All messages sent to the target class are then instead received by the posing class. There are some restrictions on which classes can pose:

  • A class may only pose as one of its direct or indirect superclasses
  • The posing class must not define any new instance variables which are absent from the target class (though it may define or override methods).
  • No messages must have been sent to the target class prior to the posing.

Posing, similarly to categories, allows globally augmenting existing classes. Posing permits two features absent from categories:

  • A posing class can call overridden methods through super, thus incorporating the implementation of the target class.
  • A posing class can override methods defined in categories.

An example:

@interface CustomNSApplication : NSApplication
@end

@implementation CustomNSApplication
- (void) setMainMenu: (NSMenu*) menu
{
     // do something with menu
}
@end

class_poseAs ([CustomNSApplication class], [NSApplication class]);

This intercepts every invocation of setMainMenu to NSApplication.

Rath answered 17/10, 2008 at 10:6 Comment(2)
Class_poseAs is deprecated starting in 10.5. The replacement is doing the same on a method by method basis, which is now explicitly supported in the runtime.Nachison
Oops, forgot to link the docs.Nachison
D
15

Object Forwarding/Method Missing

When an object is sent a message for which it has no method, the runtime system gives it another chance to handle the call before giving up. If the object supports a -forward:: method, the runtime calls this method, passing it information about the unhandled call. The return value from the forwarded call is propagated back to the original caller of the method.

-(retval_t)forward:(SEL)sel :(arglist_t)args {
  if ([myDelegate respondsTo:sel])
 return [myDelegate performv:sel :args]
 else
 return [super forward:sel :args];
 }

Content from Objective-C Pocket Reference

This is very powerful and is used heavily in the Ruby community for the various DSLs and rails, etc. Originated in Smalltalk which influenced both Objective-C and Ruby.

Dietz answered 17/10, 2008 at 10:6 Comment(2)
I would recommend using the documented method ´-[NSObject forwardInvocation:]` instead. The undocumented method -[Object forward::] is deprecated since long, and no longer available in the modern Objective-C run-time. Such as 64bit and ARM on iOS devices.Bamako
Does anyone know if this still works? I can't seem to find any documentation on this at all.Overpay
V
11

ISA Switching

Need to override all of an object's behaviors? You can actually change the class of an active object with a single line of code:

obj->isa = [NewClass class];

This only changes the class that receives method calls for that object; it doesn't change the object's layout in memory. Thus, this is only really useful when you have a set of classes with the same ivars (or one with a subset of the others') and you want to switch between them.

One piece of code I've written uses this for lazy loading: it allocates an object of class A, fills a couple critical ivars (in this case, mainly a record number) and switches the isa pointer to point to LazyA. When any method other than a very small set like release and retain is called, LazyA loads all the data from disk, finishes filling in the ivars, switches the isa pointer back to A, and forwards the call to the real class.

Very answered 17/10, 2008 at 10:6 Comment(3)
My god, I never thought of that. I need to test this, because it's brilliant. I wonder whether there are any nasty side-effects?Jenevajeni
I tried this to answer #875406, but I get the compile error: Instance variable 'isa' is protected. Is there anyway to get around that? See #8513293Mucro
@MattDiPasquale The top answer is correct—the modern way to do it is with objc_setClass().Very
S
10

Categories

Using Categories, you can add methods to built-in classes without subclassing. Full reference.

It's nice to add convenience methods to commonly used classes, such as NSString or NSData.

Subscapular answered 17/10, 2008 at 10:6 Comment(1)
Great tip, but not quite hidden… :)Jenevajeni
M
10
#include <Foundation/Debug.h>

Lots of tools for trying to track down memory leaks, premature deallocs, and more in that header file.

Midrib answered 17/10, 2008 at 10:6 Comment(2)
That's Cocoa specific (maybe OpenSTEP too?) rather than a language feature, though since no-one uses ObjC except with Cocoa I guess it doesn't make a lot of differenceBacillus
So, that doesn't work for Cocoa Touch, i.e. iOS? What does it do exactly?Mucro
C
4

Objective-C Runtime Reference

It's easy to forget that the syntactic sugar of Objective-C is converted to normal C function calls that are the Object-C Runtime. It's likely that you will never need to actually delve into and use anything in the runtime. That is why I would consider this a 'hidden feature'.

Let me give a way one might use the runtime system.

Let's say that someone is designing an external framework API that will be used by third parties. And that someone designs a class in the framework that abstractly represents a packet of data, we'll call it MLAbstractDataPacket. Now it's up to the application who is linking in the framework to subclass MLAbstractDataPacket and define the subclass data packets. Every subclass must override the method +(BOOL)isMyKindOfDataPacket:(NSData *)data.

With that information in mind...

It would be nice if MLAbstractDataPacket provided a convenience method that returned the correct initialized class for a packet of data that comes in the form +(id)initWithDataPacket:(NSData *)data.

There's only one problem here. The superclass doesn't know about any of its subclasses. So here you could use the runtime method objc_getClassList() along with objc_getSuperclass() to find the classes that are subclasses of MLAbstractDataPacket. Once you have a list of subclasses you can then try +isMyKindOfDataPacket: on each until one is found or not found.

The reference information about this can be found at http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html.

Carnap answered 17/10, 2008 at 10:6 Comment(0)
A
0

I like the verbose method naming like [myArray writeToFile:myPath atomically:YES], where every argument has a label.

Annmarie answered 17/10, 2008 at 10:6 Comment(3)
How is that hidden?... :)Aphonic
@Psionides: It's pretty obvious to people that actually use the language I agree, but most people coming from some other language most people seem to miss this simple fact. at least the folks I've spoken with.Annmarie
You can't miss it! Not if you actually want to pass messages!Hygrometer

© 2022 - 2024 — McMap. All rights reserved.