程序员iOS学习笔记iOS Developer

多此一举的调用?从 NSInvocation 看命令模式

2019-01-27  本文已影响19人  溪石iOS
命令模式

命令模式是一种将方法调用封装为对象的设计模式,在iOS中具体实现为NSInvocation,你可以从NSInvocation的设计中体会命令模式的具体实现思路。NSInvocation将执行一个方法的所有一切信息都打包在一起,分为四部分:

  1. 目标:接收消息的对象 。
  2. 选择器:被发送的消息。
  3. 方法签名:用来获得方法的返回类型和参数类型。
  4. 参数:可以添加任意数量的参数。

下面来看看NSInvocation 的实际使用:

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSMethodSignature *sig = [self methodSignatureForSelector:@selector(doSomeThing:)]; // 方法签名
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
    invocation.target = self; // 目标
    invocation.selector = @selector(doSomeThing:); // 选择器
    NSString *arg1 = @"Xishi";
    [invocation setArgument:&arg1 atIndex:2]; // 参数
    [invocation invoke]; // 执行
}

- (void)doSomeThing:(NSString *)arg1 {
    NSLog(@"doSomeThing被调用,arg1 = %@", arg1);
}
@end

传递参数时,第二个参数atIndex2开始index 0~1分别是目标选择器,由NSInvocation自动传递,所以假设有3个参数的方法:

- (void)doSomeThing:(NSString *)arg1 arg2:(NSString *)arg2 arg3:(NSString *)arg3 {
    NSLog(@"doSomeThing被调用,arg1 = %@, arg2 = %@, arg3 = %@", arg1, arg2, arg3);
}

执行3个参数的方法如下:

NSMethodSignature *sig = [self methodSignatureForSelector:@selector(doSomeThing:arg2:arg3:)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
invocation.target = self;
invocation.selector = @selector(doSomeThing:arg2:arg3:);
NSString *arg1 = @"Xishi";
NSString *arg2 = @"is";
NSString *arg3 = @"Developer";
[invocation setArgument:&arg1 atIndex:2];
[invocation setArgument:&arg2 atIndex:3];
[invocation setArgument:&arg3 atIndex:4];
[invocation invoke];

执行结果如下:

doSomeThing被调用,arg1 = Xishi, arg2 = is, arg3 = Developer

由于本例子是调用当前类(self)的方法,显得比直接调用方法繁琐,不过可以看出,实际调用者只需要获得NSInvocation对象,调用invoke即可执行方法,并不需要知道具体执行对象,这对如菜单这样的“执行视图”提供了一种解耦方式,也是 forwardInvocation 和 undo 系统的基础。

上一篇 下一篇

猜你喜欢

热点阅读