将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器来响应动作,它们都具有预定义的参数:
-
没有参数
action:@selector(switchToNewsDetails)
-
1个参数表示发送消息的控件
action:@selector(switchToNewsDetails:)
-
有2个参数表示发送消息的控件和触发消息的事件:
action:@selector(switchToNewsDetails:event:)
目前还不清楚你究竟做了什么,但是考虑到你想为每个button分配一个特定的详细信息索引,你可以执行以下操作:
- 为每个button设置一个标签属性等于所需的索引
-
在
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];