ios 将参数传递给 addTarget:action:forControlEvents

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3988485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:57:37  来源:igfitidea点击:

Passing parameters to addTarget:action:forControlEvents

iosobjective-ciphonecocoa-touchuicontrolevents

提问by Pierre Espenan

I am using addTarget:action:forControlEvents like this:

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

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

and I would like to pass parameters to my selector "switchToNewsDetails". The only thing I succeed in doing is to pass the (id)sender by writing:

我想将参数传递给我的选择器“switchToNewsDetails”。我唯一能做的就是通过以下方式传递(id)发件人:

action:@selector(switchToNewsDetails:)

But I am trying to pass variables like integer values. Writing it this way doesn't work :

但我试图传递像整数值这样的变量。这样写是行不通的:

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

Writing it this way does not work either:

以这种方式编写它也不起作用:

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

Any help would be appreciated :)

任何帮助,将不胜感激 :)

回答by Vladimir

action:@selector(switchToNewsDetails:)

You do not pass parameters to switchToNewsDetails:method here. You just create a selector to make button able to call it when certain action occurs (touch up in your case). Controls can use 3 types of selectors to respond to actions, all of them have predefined meaning of their parameters:

switchToNewsDetails:此处不向方法传递参数。您只需创建一个选择器,使按钮能够在发生某些操作时调用它(在您的情况下进行修改)。控件可以使用 3 种类型的选择器来响应动作,它们都有预定义的参数含义:

  1. with no parameters

    action:@selector(switchToNewsDetails)
    
  2. with 1 parameter indicating the control that sends the message

    action:@selector(switchToNewsDetails:)
    
  3. With 2 parameters indicating the control that sends the message and the event that triggered the message:

    action:@selector(switchToNewsDetails:event:)
    
  1. 没有参数

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

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

    action:@selector(switchToNewsDetails:event:)
    

It is not clear what exactly you try to do, but considering you want to assign a specific details index to each button you can do the following:

目前尚不清楚您到底要做什么,但考虑到您想为每个按钮分配一个特定的详细信息索引,您可以执行以下操作:

  1. set a tag property to each button equal to required index
  2. in switchToNewsDetails:method you can obtain that index and open appropriate deatails:

    - (void)switchToNewsDetails:(UIButton*)sender{
        [self openDetails:sender.tag];
        // Or place opening logic right here
    }
    
  1. 为每个按钮设置一个标签属性等于所需的索引
  2. switchToNewsDetails:方法中,您可以获得该索引并打开适当的详细信息:

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

回答by Yuriy Polezhayev

To pass custom params along with the button click you just need to SUBCLASS UIButton.

要传递自定义参数和按钮单击,您只需要SUBCLASS UIButton

(ASR is on, so there's no releases in the code.)

(ASR 已启用,因此代码中没有发布版本。)

This is myButton.h

这是myButton.h

#import <UIKit/UIKit.h>

@interface myButton : UIButton {
    id userData;
}

@property (nonatomic, readwrite, retain) id userData;

@end

This is myButton.m

这是myButton.m

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

Usage:

用法:

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];

Recieving function:

接收功能:

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

If you need me to be more specific on any part of the above code — feel free to ask about it in comments.

如果您需要我对上述代码的任何部分进行更具体的说明,请随时在评论中询问。

回答by Beno?t

Target-Action allows three different forms of action selector:

Target-Action 允许三种不同形式的动作选择器:

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

回答by Albert Renshaw

Need more than just an (int) via .tag? Use KVC!

需要的不仅仅是通过 .tag 的 (int)?使用 KVC!

You can pass any data you want through the button object itself (by accessing CALayers keyValue dict).

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



Set your target like this (with the ":")

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

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


Add your data(s) to the button itself (well the .layerof the button that is) like this:

将您的数据添加到按钮本身(以及按钮本身.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!


Then when the button is tapped you can check it like this:

然后当按钮被点击时,你可以像这样检查它:

-(void)buttonTap:(UIButton*)sender{

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

}

回答by Abhinav Singh

I made a solution based in part by the information above. I just set the titlelabel.text to the string I want to pass, and set the titlelabel.hidden = YES

我部分根据上述信息制定了解决方案。我只是将 titlelabel.text 设置为我要传递的字符串,并设置 titlelabel.hidden = YES

Like this :

像这样 :

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

This way, there is no need for a inheritance or category and there is no memory leak

这样,就不需要继承或类别,也没有内存泄漏

回答by rjdunwoody91

I was creating several buttons for each phone number in an array so each button needed a different phone number to call. I used the setTag function as I was creating several buttons within a for loop:

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

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];
}

Then in my call: method I used the same for loop and an if statement to pick the correct phone number:

然后在我的 call: 方法中,我使用了相同的 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]];
        }
    }
}

回答by Kumar KL

As there are many ways mentioned here for the solution, Except category feature .

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

Use the category feature to extend defined(built-in) element into your customisable element.

使用类别功能将定义的(内置)元素扩展到可自定义的元素中。

For instance(ex) :

例如(前):

@interface UIButton (myData)

@property (strong, nonatomic) id btnData;

@end

in the your view Controller.m

在您的视图 Controller.m 中

 #import "UIButton+myAppLists.h"

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

Event handler:

事件处理程序:

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

回答by Marián ?erny

You can replace target-action with a closure (block in Objective-C) by adding a helper closure wrapper (ClosureSleeve) and adding it as an associated object to the control so it gets retained. That way you can pass any parameters.

您可以通过添加一个辅助闭包包装器 (ClosureSleeve) 并将其作为关联对象添加到控件中以将其保留,从而用闭包(Objective-C 中的块)替换 target-action。这样你就可以传递任何参数。

Swift 3

斯威夫特 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)
    }
}

Usage:

用法:

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

回答by Anton Lisitsyn

There is another one way, in which you can get indexPath of the cell where your button was pressed:

还有另一种方法,您可以获得按下按钮的单元格的 indexPath :

using usual action selector like:

使用通常的动作选择器,如:

 UIButton *btn = ....;
    [btn addTarget:self action:@selector(yourFunction:) forControlEvents:UIControlEventTouchUpInside];

and then in in yourFunction:

然后在 yourFunction 中:

   - (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
    ..
}

since you get an indexPath it becames much simplier.

因为你得到了一个 indexPath 它变得更加简单。

回答by iphaaw

This fixed my problem but it crashed unless I changed

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

action:@selector(switchToNewsDetails:event:)                 

to

action:@selector(switchToNewsDetails: forEvent:)