Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
153 views
in Technique[技术] by (71.8m points)

objective c - NSInvocation for Dummies?

How exactly does NSInvocation work? Is there a good introduction?

I’m specifically having issues understanding how the following code (from Cocoa Programming for Mac OS X, 3rd Edition) works, but then also be able to apply the concepts independently of the tutorial sample. The code:

- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index
{
    NSLog(@"adding %@ to %@", p, employees);
    // Add inverse of this operation to undo stack
    NSUndoManager *undo = [self undoManager];
    [[undo prepareWithInvocationTarget:self] removeObjectFromEmployeesAtIndex:index];
    if (![undo isUndoing])
        [undo setActionName:@"Insert Person"];

    // Finally, add person to the array
    [employees insertObject:p atIndex:index];
}

- (void)removeObjectFromEmployeesAtIndex:(int)index
{
    Person *p = [employees objectAtIndex:index];
    NSLog(@"removing %@ from %@", p, employees);
    // Add inverse of this operation to undo stack
    NSUndoManager *undo = [self undoManager];
    [[undo prepareWithInvocationTarget:self] insertObject:p
                                       inEmployeesAtIndex:index];
    if (![undo isUndoing])
        [undo setActionName:@"Delete Person"];

    // Finally, remove person from array
    [employees removeObjectAtIndex:index];
}

I get what it’s trying to do. (BTW, employees is an NSArray of a custom Person class.)

Being a .NET guy, I try to associate unfamiliar Obj-C and Cocoa concepts to roughly analogous .NET concepts. Is this similar to .NET’s delegate concept, but untyped?

This isn’t 100% clear from the book, so I’m looking for something supplemental from real Cocoa/Obj-C experts, again with the goal that I understand the fundamental concept beneath the simple(-ish) example. I'm really looking to be able to independently apply the knowledge -- up until chapter 9, I was having no difficulty doing that. But now ...

Thanks in advance!

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

According to Apple's NSInvocation class reference:

An NSInvocation is an Objective-C message rendered static, that is, it is an action turned into an object.

And, in a little more detail:

The concept of messages is central to the objective-c philosophy. Any time you call a method, or access a variable of some object, you are sending it a message. NSInvocation comes in handy when you want to send a message to an object at a different point in time, or send the same message several times. NSInvocation allows you to describe the message you are going to send, and then invoke it (actually send it to the target object) later on.


For example, let's say you want to add a string to an array. You would normally send the addObject: message as follows:

[myArray addObject:myString];

Now, let's say you want to use NSInvocation to send this message at some other point in time:

First, you would prepare an NSInvocation object for use with NSMutableArray's addObject: selector:

NSMethodSignature * mySignature = [NSMutableArray
    instanceMethodSignatureForSelector:@selector(addObject:)];
NSInvocation * myInvocation = [NSInvocation
    invocationWithMethodSignature:mySignature];

Next, you would specify which object to send the message to:

[myInvocation setTarget:myArray];

Specify the message you wish to send to that object:

[myInvocation setSelector:@selector(addObject:)];

And fill in any arguments for that method:

[myInvocation setArgument:&myString atIndex:2];

Note that object arguments must be passed by pointer. Thank you to Ryan McCuaig for pointing that out, and please see Apple's documentation for more details.

At this point, myInvocation is a complete object, describing a message that can be sent. To actually send the message, you would call:

[myInvocation invoke];

This final step will cause the message to be sent, essentially executing [myArray addObject:myString];.

Think of it like sending an email. You open up a new email (NSInvocation object), fill in the address of the person (object) who you want to send it to, type in a message for the recipient (specify a selector and arguments), and then click "send" (call invoke).

See Using NSInvocation for more information. See Using NSInvocation if the above is not working.


NSUndoManager uses NSInvocation objects so that it can reverse commands. Essentially, what you are doing is creating an NSInvocation object to say: "Hey, if you want to undo what I just did, send this message to that object, with these arguments". You give the NSInvocation object to the NSUndoManager, and it adds that object to an array of undoable actions. If the user calls "Undo", NSUndoManager simply looks up the most recent action in the array, and invokes the stored NSInvocation object to perform the necessary action.

See Registering Undo Operations for more details.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...