Передача параметров в 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];
любая помощь будет оценили :)
12 ответов:
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 }
чтобы передать пользовательские параметры вместе с кнопкой мыши вам просто нужно подкласс 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