将parameter passing给addTarget:action:forControlEvents

我正在使用addTarget:action:forControlEvents像这样:

[newsButton addTarget:self action:@selector(switchToNewsDetails) forControlEvents:UIControlEventTouchUpInside]; 

我想将parameter passing给我的select器“switchToNewsDetails”。 我成功做的唯一的事情是通过写(ID)发送者:

 action:@selector(switchToNewsDetails:) 

但我想传递整数值的variables。 用这种方式来写就行不通了:

 int i = 0; [newsButton addTarget:self action:@selector(switchToNewsDetails:i) forControlEvents:UIControlEventTouchUpInside]; 

用这种方式写这个也不行:

 int i = 0; [newsButton addTarget:self action:@selector(switchToNewsDetails:i:) forControlEvents:UIControlEventTouchUpInside]; 

任何帮助将不胜感激:)

 action:@selector(switchToNewsDetails:) 

您不会将parameter passing给switchToNewsDetails:方法。 您只需创build一个select器,使button在发生某些操作时可以调用它(触摸您的情况)。 控件可以使用3种types的select器来响应动作,它们都具有预定义的参数:

  1. 没有参数

     action:@selector(switchToNewsDetails) 
  2. 1个参数表示发送消息的控件

     action:@selector(switchToNewsDetails:) 
  3. 有2个参数表示发送消息的控件和触发消息的事件:

     action:@selector(switchToNewsDetails:event:) 

目前还不清楚你究竟做了什么,但是考虑到你想为每个button分配一个特定的详细信息索引,你可以执行以下操作:

  1. 为每个button设置一个标签属性等于所需的索引
  2. switchToNewsDetails:方法中你可以获得该索引并打开适当的deatails:

     - (void)switchToNewsDetails:(UIButton*)sender{ [self openDetails:sender.tag]; // Or place opening logic right here } 

要传递自定义参数与button单击您只需要SUBCLASS UIButton

(ASR打开,所以代码中没有任何发布。)

这是myButton.h

 #import <UIKit/UIKit.h> @interface myButton : UIButton { id userData; } @property (nonatomic, readwrite, retain) id userData; @end 

这是myButton.m

 #import "myButton.h" @implementation myButton @synthesize userData; @end 

用法:

 myButton *bt = [myButton buttonWithType:UIButtonTypeCustom]; [bt setFrame:CGRectMake(0,0, 100, 100)]; [bt setExclusiveTouch:NO]; [bt setUserData:**(insert user data here)**]; [bt addTarget:self action:@selector(touchUpHandler:) forControlEvents:UIControlEventTouchUpInside]; [view addSubview:bt]; 

接收function:

 - (void) touchUpHandler:(myButton *)sender { id userData = sender.userData; } 

如果您需要我对上述代码的任何部分更具体,请随时在评论中提出。

Target-Action允许三种不同forms的动作select器:

 - (void)action - (void)action:(id)sender - (void)action:(id)sender forEvent:(UIEvent *)event 

我根据上面的信息提出了一个解决scheme。 我只是将titlelabel.text设置为我想传递的string,并设置titlelabel.hidden = YES

喜欢这个 :

 UIButton *imageclick = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; imageclick.frame = photoframe; imageclick.titleLabel.text = [NSString stringWithFormat:@"%@.%@", ti.mediaImage, ti.mediaExtension]; imageclick.titleLabel.hidden = YES; 

这样,就不需要inheritance或类别,并且没有内存泄漏

我为数组中的每个电话号码创build了几个button,因此每个button都需要一个不同的电话号码来呼叫。 我使用setTag函数,因为我正在for循环中创build几个button:

 for (NSInteger i = 0; i < _phoneNumbers.count; i++) { UIButton *phoneButton = [[UIButton alloc] initWithFrame:someFrame]; [phoneButton setTitle:_phoneNumbers[i] forState:UIControlStateNormal]; [phoneButton setTag:i]; [phoneButton addTarget:self action:@selector(call:) forControlEvents:UIControlEventTouchUpInside]; } 

然后在我的电话:方法我使用相同的循环和一个if语句来select正确的电话号码:

 - (void)call:(UIButton *)sender { for (NSInteger i = 0; i < _phoneNumbers.count; i++) { if (sender.tag == i) { NSString *callString = [NSString stringWithFormat:@"telprompt://%@", _phoneNumbers[i]]; [[UIApplication sharedApplication] openURL:[NSURL URLWithString:callString]]; } } } 

您可以通过button对象本身传递任何您想要的数据(通过访问CALayers keyValue字典)。


像这样设置你的目标(用“:”)

 [myButton addTarget:self action:@selector(buttonTap:) forControlEvents:UIControlEventTouchUpInside]; 

将您的数据添加到button本身,如下所示:

 NSString *dataIWantToPass = @"this is my data";//can be anything, doesn't have to be NSString [myButton.layer setValue:dataIWantToPass forKey:@"anyKey"];//you can set as many of these as you'd like too! 

然后当button被点击时,你可以这样检查:

 -(void)buttonTap:(UIButton*)sender{ NSString *dataThatWasPassed = (NSString *)[sender.layer valueForKey:@"anyKey"]; NSLog(@"My passed-thru data was: %@", dataThatWasPassed); } 

由于这里提到的解决方法有很多种,除了类别function。

使用类别function将定义的(内置)元素扩展到您的可定制元素中。

例如(ex):

 @interface UIButton (myData) @property (strong, nonatomic) id btnData; @end 

在你的视图Controller.m中

  #import "UIButton+myAppLists.h" UIButton *myButton = // btn intialisation.... [myButton set btnData:@"my own Data"]; [myButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; 

事件处理器:

 -(void)buttonClicked : (UIButton*)sender{ NSLog(@"my Data %@", sender. btnData); } 

看到我上面的评论,我相信你有不止一个参数时使用NSInvocation

更多关于NSInvocation的信息

http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html

这解决了我的问题,但它崩溃,除非我改变

 action:@selector(switchToNewsDetails:event:) 

 action:@selector(switchToNewsDetails: forEvent:) 

你可以用一个闭包(Objective-C中的块)replacetarget-action,方法是添加一个helper闭包(ClosureSleeve)并将其作为一个关联对象添加到控件中,以便保留它。 这样你可以传递任何参数。

Swift 3

 class ClosureSleeve { let closure: () -> () init(attachTo: AnyObject, closure: @escaping () -> ()) { self.closure = closure objc_setAssociatedObject(attachTo, "[\(arc4random())]", self, .OBJC_ASSOCIATION_RETAIN) } @objc func invoke() { closure() } } extension UIControl { func addAction(for controlEvents: UIControlEvents, action: @escaping () -> ()) { let sleeve = ClosureSleeve(attachTo: self, closure: action) addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents) } } 

用法:

 button.addAction(for: .touchUpInside) { self.switchToNewsDetails(parameter: i) } 

我在CustomButton中分类了UIButton,并添加了一个属性来存储我的数据。 所以我打电话给方法:( CustomButton *)发件人和方法我只读取我的数据sender.myproperty。

示例CustomButton:

 @interface CustomButton : UIButton @property(nonatomic, retain) NSString *textShare; @end 

方法操作:

 + (void) share: (CustomButton*) sender { NSString *text = sender.textShare; //your work… } 

分配行动

  CustomButton *btn = [[CustomButton alloc] initWithFrame: CGRectMake(margin, margin, 60, 60)]; // other setup… btnWa.textShare = @"my text"; [btn addTarget: self action: @selector(shareWhatsapp:) forControlEvents: UIControlEventTouchUpInside];