我正在使用addTarget:action:forControlEvents,如下所示:
[newsButton addTarget:self
action:@selector(switchToNewsDetails)
forControlEvents:UIControlEventTouchUpInside];
我想将参数传递给我的选择器“switchToNewsDetails”。 我成功的唯一方法是通过写入来传递(id)发件人:
action:@selector(switchToNewsDetails:)
但我试图传递整数值之类的变量。以这种方式编写不起作用:
int i = 0;
[newsButton addTarget:self
action:@selector(switchToNewsDetails:i)
forControlEvents:UIControlEventTouchUpInside];
以这种方式编写它也不起作用:
int i = 0;
[newsButton addTarget:self
action:@selector(switchToNewsDetails:i:)
forControlEvents:UIControlEventTouchUpInside];
任何帮助将不胜感激:)
答案 0 :(得分:171)
action:@selector(switchToNewsDetails:)
此处不会将参数传递给switchToNewsDetails:
方法。您只需创建一个选择器,使按钮能够在发生特定操作时调用它(在您的情况下触摸)。控件可以使用3种类型的选择器来响应操作,所有这些操作都具有预定义的参数含义:
没有参数
action:@selector(switchToNewsDetails)
带有1个参数,表示发送消息的控件
action:@selector(switchToNewsDetails:)
使用2个参数指示发送消息的控件和触发消息的事件:
action:@selector(switchToNewsDetails:event:)
目前尚不清楚您尝试做什么,但考虑到您想为每个按钮指定特定的详细信息索引,您可以执行以下操作:
在switchToNewsDetails:
方法中,您可以获取该索引并打开相应的deatails:
- (void)switchToNewsDetails:(UIButton*)sender{
[self openDetails:sender.tag];
// Or place opening logic right here
}
答案 1 :(得分:63)
要通过自定义参数和按钮点击,您只需要 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];
接收功能:
- (void) touchUpHandler:(myButton *)sender {
id userData = sender.userData;
}
如果您需要我更具体地了解上述代码的任何部分 - 请随时在评论中询问。
答案 2 :(得分:19)
Target-Action允许三种不同形式的动作选择器:
- (void)action
- (void)action:(id)sender
- (void)action:(id)sender forEvent:(UIEvent *)event
答案 3 :(得分:15)
您可以通过按钮对象本身传递您想要的任何数据(通过访问CALayers keyValue dict)。
像这样设置目标(使用&#34;:&#34;)
[myButton addTarget:self action:@selector(buttonTap:) forControlEvents:UIControlEventTouchUpInside];
将您的数据添加到按钮本身(以及按钮的.layer
),如下所示:
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!
然后,当点击按钮时,您可以这样检查:
-(void)buttonTap:(UIButton*)sender{
NSString *dataThatWasPassed = (NSString *)[sender.layer valueForKey:@"anyKey"];
NSLog(@"My passed-thru data was: %@", dataThatWasPassed);
}
答案 4 :(得分:7)
我部分地根据上述信息制定了解决方案。我只是将titlelabel.text设置为我想传递的字符串,并设置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;
这样,就不需要继承或类别,也没有内存泄漏
答案 5 :(得分:5)
我为阵列中的每个电话号码创建了几个按钮,因此每个按钮都需要一个不同的电话号码才能呼叫。我使用了setTag函数,因为我在for循环中创建了几个按钮:
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];
}
然后在我的电话中:方法我使用相同的for循环和if语句来选择正确的电话号码:
- (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]];
}
}
}
答案 6 :(得分:2)
由于这里提到了解决方案的方法很多,除了类别功能。
使用类别功能将已定义的(内置)元素扩展到您的 可定制的元素。
例如(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);
}
答案 7 :(得分:2)
还有另一种方法,你可以在其中获得按下按钮的单元格的indexPath:
使用常用的动作选择器,如:
UIButton *btn = ....;
[btn addTarget:self action:@selector(yourFunction:) forControlEvents:UIControlEventTouchUpInside];
然后在你的函数中:
- (void) yourFunction:(id)sender {
UIButton *button = sender;
CGPoint center = button.center;
CGPoint rootViewPoint = [button.superview convertPoint:center toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rootViewPoint];
//the rest of your code goes here
..
}
因为你获得了一个indexPath,所以它更简单。
答案 8 :(得分:1)
请参阅上面的评论,我相信当有多个参数时你必须使用NSInvocation
有关NSInvocation的更多信息
http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html
答案 9 :(得分:1)
这解决了我的问题,但除非我改变了
,否则它会崩溃action:@selector(switchToNewsDetails:event:)
到
action:@selector(switchToNewsDetails: forEvent:)
答案 10 :(得分:1)
您可以通过添加辅助闭包装置(ClosureSleeve)并将其作为关联对象添加到控件中来替换目标操作和闭包(Objective-C中的块),以便保留它。这样你就可以传递任何参数。
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)
}
答案 11 :(得分:0)
我在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];
答案 12 :(得分:0)
如果您只想更改导航控制器显示的leftBarButtonItem的文本以及新视图,则可以在将pushViewController调用为所需文本之前更改当前视图的标题,并在viewHasDisappered回调中将其还原为当前视图的未来显示。
这种方法可以使功能(popViewController)和所示箭头的外观保持完整。
至少在iOS 12上,它对我们有效,该平台使用Xcode 10.1 ...