NSInvocation和NSUndoManager的关系

NSInvocation是一个非常特别的对象,这个对象将一个对象的消息(通常在其他语言中我们称之为函数)封装成一个对象。然后在不同的对象之间进行传递。

一个比较典型的场景是说,当一个对象在被调用一个他并不是别的消息(函数)时,他会查找他的forwardInvocation方法,如果实现了forwardInvocation方法,那么在这个方法当中,会将不能够被识别的消息,封装为NSInvocation对象,然后发送下去。

因此,NSInvocation的比较典型的应用就是消息的转发。或者说是函数功能的转发。


补充一下,对于一个对象,调用函数的方法,其实有如下方法:

1、【object fun】;

2、 【object performselect:withObject】;这种方法可以完成简单的调用关系,对于参数》2时,就需要做额外的处理。那么方法3就比较简单

3、NSInvocation方法。

关于3的实例:

[html]  view plain copy
  1. #import <Foundation/Foundation.h>  
  2. #import "MyClass.h"  
  3.   
  4. int main (int argc, const char * argv[])  
  5. {  
  6.   
  7.     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  
  8.   
  9.     MyClass *myClass = [[MyClass alloc] init];  
  10.     NSString *myString = @"My string";  
  11.       
  12.     //普通调用  
  13.     NSString *normalInvokeString = [myClass appendMyString:myString];  
  14.     NSLog(@"The normal invoke string is: %@", normalInvokeString);  
  15.       
  16.     //NSInvocation调用  
  17.     SEL mySelector = @selector(appendMyString:);  
  18.     NSMethodSignature * sig = [[myClass class]   
  19.                                instanceMethodSignatureForSelector: mySelector];  
  20.       
  21.     NSInvocation * myInvocation = [NSInvocation invocationWithMethodSignature: sig];  
  22.     [myInvocation setTarget: myClass];  
  23.     [myInvocation setSelector: mySelector];  
  24.       
  25.     [myInvocation setArgument: &myString atIndex: 2];  
  26.       
  27.     NSString * result = nil;      

这里说明一下[myInvocation setArgument: &myString atIndex: 2];为什么index从2开始

文档中的说明

Indices 0 and 1 indicate the hidden arguments self and _cmd, respectively; you should set these values directly with the setTarget: and setSelector: methods. Use indices 2 and greater for the arguments normally passed in a message.意思就是0和1是隐藏参数,而这两个参数是要在setTarget和setSelector设置的,所以我们调用方法中的参数就要从2开始了,如果有多个参数,那么就依次递增。


那么他的比较典型的应用,就是来源于对于撤销和重做的功能,在NSUndoManager当中,其实提供了两个栈,一个是undo的栈,另一个是redo的栈,然后用户在进行了对应的操作之后,会将该操作的逆操作记录到undo栈当中,这样当用户触发undo时,undomanager,或者叫做undo管理器会调用栈中的方法,从而实现undo操作,然后undo管理器,会将undo操作放到redo栈当中,等待用户出发redo操作。


实例:


- (void) walkLeft
{
    position = position + 10;
    [[undoManager prepareWithInvocationTarget:self] walkRight];
    [self showTheChangesToThePostion];
}

    prepareWithInvocationTarget:方法记录了target并返回UndoManager,然后UndoManager重载了forwardInvocation方法,也就将walkRight方法的Invocation添加到undo栈中了。
   
- (void) walkRight
{
    position = position - 10;
    [[undoManager prepareWithInvocationTarget:self] walkLeft];
    [self showTheChangesToThePostion];

}


此外:

    UndoManager还可以设置撤销菜单动作的名称:
    [undoManager setActionName:@"Insert"];

你可能感兴趣的:(html,object,cmd,文档,insert,fun)