就像UIButton
我可以:
[button addTarget:target forSelector:@selector(action)]
或者:
[button addTarget:target forSelector:@selector(action:)]
在第二个按钮中,按钮的动作将有一个发送者(作为按钮本身),如何确定给定的选择器是否有参数,以便我可以传递给它?
答案 0 :(得分:3)
作为第一关,我会使用NSStringFromSelector()
。如果出于某种原因给你带来问题,我会使用sel_getName
。
NSInteger MYParameterCountOfSelector(SEL selector) {
NSString *string = NSStringFromSelector(selector);
return [string componentsSeparatedByString:@":"].count - 1;
}
答案 1 :(得分:2)
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)(假设你在模拟器中。如果你想要所有正确的寄存器,你需要{{ 3}})。来自我的(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中执行此操作的典型方法就是设置,这样你就可以随时发送所有内容并让接收者忽略它。 / p>