多此一举的调用?从 NSInvocation 看命令模式
2019-01-27 本文已影响19人
溪石iOS
![](https://img.haomeiwen.com/i2025746/60f3ba27e7cf9e02.jpeg)
命令模式是一种将方法调用封装为对象的设计模式,在iOS中具体实现为NSInvocation,你可以从NSInvocation的设计中体会命令模式的具体实现思路。NSInvocation将执行一个方法的所有一切信息都打包在一起,分为四部分:
-
目标
:接收消息的对象 。 -
选择器
:被发送的消息。 -
方法签名
:用来获得方法的返回类型和参数类型。 -
参数
:可以添加任意数量的参数。
下面来看看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
传递参数时,第二个参数atIndex
从 2开始
,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 系统的基础。