Передача параметров 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]; 

Любая помощь будет оценена 🙂

 action:@selector(switchToNewsDetails:) 

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

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

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

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

     action:@selector(switchToNewsDetails:event:) 

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

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

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

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

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

Это myButton.h

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

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

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

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

Вы можете передать любые данные, которые вы хотите, через сам объект кнопки (путем доступа к 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); } 

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

Как это :

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

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

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

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

Например, например:

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

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

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

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

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

Я подclassифицировал 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]; 
  • Перемещение UIView (изображение и текст)
  • Использование Swift CFunctionPointer для передачи обратного вызова API CoreMIDI
  • Восстановить пре-iOS7 UINavigationController pushViewController animation
  • CALayer: добавить границу только с одной стороны
  • Масштабирование MKMapView для подгонки аннотаций?
  • Полужирный и нежирный текст в одном UILabel?
  • Использование iPhone - dequeueReusableCellWithIdentifier
  • objective-C - Когда использовать «я»,
  • Сортировка NSArray строк или объектов даты
  • UISlider для управления AVAudioPlayer
  • Разбор даты JSON на IPhone
  • Давайте будем гением компьютера.