Передача параметров в addTarget: действие: forControlEvents



Я использую 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];


любая помощь будет оценили :)

497   12  

12 ответов:

action:@selector(switchToNewsDetails:)

вы не передаете параметры в switchToNewsDetails: способ здесь. Вы просто создаете селектор, чтобы кнопка могла вызывать его, когда происходит определенное действие (коснитесь в вашем случае). Элементы управления могут использовать 3 типа селекторов для ответа на действия, все они имеют предопределенное значение своих параметров:

  1. без параметров

    action:@selector(switchToNewsDetails)
    
  2. С 1 параметром, указывающим на элемент управления, который отправляет сообщение

    action:@selector(switchToNewsDetails:)
    
  3. С 2 параметрами, указывающими на элемент управления, который отправляет сообщение и событие, которое вызвало сообщение:

    action:@selector(switchToNewsDetails:event:)
    

неясно, что именно вы пытаетесь сделать, но, учитывая, что вы хотите назначить конкретный индекс деталей для каждой кнопки, вы можете сделать следующее:

  1. установите свойство тега для каждой кнопки, равное требуемому индексу
  2. на switchToNewsDetails: метод вы можете получить вот индекс и откройте соответствующие deatails:

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

чтобы передать пользовательские параметры вместе с кнопкой мыши вам просто нужно подкласс UIButton.

(ASR включен, поэтому в коде нет релизов.)

это myButton.h

#import <UIKit/UIKit.h>

@interface myButton : UIButton {
    id userData;
}

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

@end

это myButton.м

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

Если вам нужно, чтобы я был более конкретным в любой части приведенного выше кода - не стесняйтесь спросите об этом в комментариях.

Target-Action позволяет три различных формы селектора действий:

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

нужно больше, чем просто (int) через .тег? Использование КВК!

вы можете передать любые данные, которые вы хотите через сам объект button (путем доступа к CALayers keyValue dict).


установите свою цель вот так (с помощью ":")

[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);

}

Я сделал решение, основанное частично на информации выше. Я только что установил метку заголовка.текст в строку, которую я хочу передать, и установите метку заголовка.скрытый = да

такой :

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

таким образом, нет необходимости в наследовании или категории и нет утечки памяти

Я создавал несколько кнопок для каждого номера телефона в массиве, поэтому каждая кнопка нуждалась в другом номере телефона для вызова. Я использовал функцию 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];
}

затем в моем вызове: метод я использовал то же самое для цикла и оператора 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]];
        }
    }
}

как есть много способов, упомянутых здесь решения, за исключением категории .

используйте функцию категории для расширения определенного (встроенного) элемента в ваш настраиваемый элемент.

например (ex):

@interface UIButton (myData)

@property (strong, nonatomic) id btnData;

@end

в контроллере вашего вида.м

 #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);
}

есть еще один способ, в котором вы можете получить indexPath ячейки, где ваша кнопка была нажата:

используя обычный селектор действий, например:

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

а затем в in 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
    ..
}

так как вы получаете indexPath он становится намного проще.

смотрите мой комментарий выше, и я считаю, что вы должны использовать NSInvocation, когда есть более одного параметра

больше информации о NSInvocation здесь

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

это исправило мою проблему, но он разбился, если я не изменил

action:@selector(switchToNewsDetails:event:)                 

до

action:@selector(switchToNewsDetails: forEvent:)              

вы можете заменить целевое действие закрытием (блок в Objective-C), добавив вспомогательную оболочку закрытия (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)
}

Я подкласс UIButton в CustomButton и я добавляю свойство, где я храню свои данные. Поэтому я вызываю метод: (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];

Comments

    Ничего не найдено.