Jeffery 是对的(许多动态 ObjC 都是通过这种方式处理选择器而不是深入到 NSMethodSignature 的胆量来处理的,这会为您提供更精确的信息)。但同样,你总是可以传递一些东西。我知道这听起来很疯狂,但传递太多东西在 ObjC 中实际上并不是问题。
@interface MyObject: NSObject
- (void)something;
@end
...
MyObject *object = [MyObject new];
[object performSelector:@selector(something) withObject:@"thing"];
工作正常。什么!?!?是的。这实际上是您的按钮示例的工作方式。在IBAction 中设置断点,然后查看调用者:
0x108b21d2c <+58>: movq 0x1400a1d(%rip), %rsi ; "performSelector:withObject:withObject:"
0x108b21d33 <+65>: movq %rbx, %rdi
0x108b21d36 <+68>: movq %r12, %rdx
0x108b21d39 <+71>: movq %r15, %rcx
0x108b21d3c <+74>: movq %r14, %r8
0x108b21d3f <+77>: callq *0x10ac7f3(%rip) ; (void *)0x0000000108019ac0: objc_msgSend
它总是调用performSelector:withObject:withObject: 并将发送者和事件传递给你,即使你没有要求它们。如果您不相信我,请尝试查看 $rdx (arg2) 和 $rcx (arg3)(假设您在模拟器中。如果您想要所有正确的寄存器,您会想要 the list)。来自我的(IBAction)doThing 方法:
(lldb) po $rdx
<UIButton: 0x7f8071a126f0; frame = (164 318; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x608000223140>>
(lldb) po $rcx
<UITouchesEvent: 0x6180001068a0> timestamp: 1.06651e+06 touches: {(
<UITouch: 0x7f8070500e20> phase: Ended tap count: 1 force: 0.000 window: <UIWindow: 0x7f8071a10890; frame = (0 0; 414 736); autoresize = W+H; gestureRecognizers = <NSArray: 0x60800026dbc0>; layer = <UIWindowLayer: 0x608000222800>> view: <UIButton: 0x7f8071a126f0; frame = (164 318; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x608000223140>> location in window: {205, 335} previous location in window: {205, 335} location in view: {41, 17} previous location in view: {41, 17}
)}
所以是的,您可以拆开选择器并确定要发送或不发送的内容,但在 Cocoa 中执行此操作的典型方法只是进行设置,以便您始终可以发送所有内容并让接收者忽略它。