Grab that Invocation

CInvocationGrabber is a Cocoa class to help with creating NSInvocation objects.

NSInvocation objects are Cocoa’s equivalent of “functors” and are extremely handy. But unfortunately creating them is often a pain. For example, take the following code showing how to create a simple NSInvocation:

NSInvocation *theInvocation = [NSInvocation invocationWithMethodSignature:[theString methodSignatureForSelector:@selector(insertString:atIndex:)]];
[theInvocation setSelector:@selector(insertString:atIndex:)];
[theInvocation setTarget:theString];
NSString *theFirstArgument = "Hello World";
[theInvocation setArgument:&theFirstArgument atIndex:2];
unsigned theSecondArgument = 42;
[theInvocation setArgument:&theFirstArgument atIndex:3];

The code to create the same NSInvocation using my CInvocationGrabber class looks like this:

CInvocationGrabber *theGrabber = [CInvocationGrabber invocationGrabber];
[[theGrabber prepareWithInvocationTarget:theString] insertString:@"Hello World" atIndex:42];
NSInvocation *theInvocation = [theGrabber invocation]

Obviously the primary benefit is that there is a lot less code. A secondary benefit is that you don’t have to store your parameters on the heap and can just pass them into the ‘grabbed’ method.

Now that I’ve been using CInvocationGrabber for a few months I find I am using NSInvocations more and more. I’m using them in places where I would normally have written a little delegate method. For example just today I needed to write code that called a method after a time delay. Normally I would have wrapped it up in a NSTimer delegate method, but with CInvocationHelper I just used the invocation variant of NSTimer. Although I wasn’t saving many lines of code in this example, I was reducing the clutter in the class.

Cocoa developers with a keen eye might spot the similarity between CInvocationGrabber and Cocoa’s NSUndoManager APIs. This code is directly inspired by NSUndoManager’s prepareWithInvocation method.

This entry was posted in Default and tagged , , . Bookmark the permalink.
  • chrome
    Great work; saved me a bunch of time writing this myself.
  • Richard Stacpoole
    Thanks,

    I have just started using NSInvocation, and this will be useful.

    Also there is a bug in your first code box, you have &firstArgument twice.
  • Nice work! One possible enhancement might be to change the invocation "capture" so that it can record multiples on an array. Then the client could ask for an array of all invocations sent to it. It could even sport a "performInvocationsOnObject:" method.

    Also, the name "CInvocationRecorder" might better represent what this thing does, especially if multi-recording was added.
blog comments powered by Disqus