Передача параметров для действия кнопки: @selector - PullRequest
50 голосов
/ 15 сентября 2010

Я хочу передать URL фильма из динамически сгенерированной кнопки в MediaPlayer:

[button addTarget:self action:@selector(buttonPressed:) withObject:[speakers_mp4 objectAtIndex:[indexPath row]] forControlEvents:UIControlEventTouchUpInside];

но action:@selector() withObject: не работает?

Есть ли другое решение?

Спасибо за помощь!

Ответы [ 11 ]

61 голосов
/ 08 февраля 2011

Редактировать.Найден более аккуратный способ!

Один аргумент, который может получить кнопка - (id)sender.Это означает, что вы можете создать новую кнопку, унаследованную от UIButton, которая позволит вам хранить другие предполагаемые аргументы.Надеюсь, эти два фрагмента иллюстрируют, что делать.

  myOwnbutton.argOne = someValue
  [myOwnbutton addTarget:self action:@selector(buttonTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];

и

- (IBAction) buttonTouchUpInside:(id)sender {
  MyOwnButton *buttonClicked = (MyOwnButton *)sender; 
  //do as you please with buttonClicked.argOne
}

Это было мое первоначальное предложение.

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

[button addTarget:self action:@selector(navigate) forControlEvents:UIControlEventTouchUpInside];

Чтобы обойти это, вы можете переместить навигацию method в собственный класс и установить "параметры" в качестве атрибутов этого класса ...

NavigationAid *navAid = [[NavigationAid alloc] init];
navAid.firstParam = someVariableOne
navAid.secondParam = someVariableTwo
[button addTarget:navAid action:@selector(navigate) forControlEvents:UIControlEventTouchUpInside];

Конечно, вы можете сохранить метод navigate в исходном классе и вызывать его с помощью navAid, если он знает, где его найти.

NavigationAid *navAid = [[NavigationAid alloc] init];
navAid.whereToCallNavigate = self
navAid.firstParam = someVariableOne
navAid.secondParam = someVariableTwo
[button addTarget:navAid action:@selector(navigate) forControlEvents:UIControlEventTouchUpInside];

Как я уже сказал, это не красиво, но он работал дляя и я не нашли никого, кто предлагал бы другое рабочее решение.

32 голосов
/ 09 июня 2011

Я нашел решение. Звонок:

-(void) someMethod{
    UIButton * but;
    but.tag = 1;//some id button that you choice 
    [but addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; 
}

И вот этот метод называется:

-(void) buttonPressed : (id) sender{
    UIButton *clicked = (UIButton *) sender;
    NSLog(@"%d",clicked.tag);//Here you know which button has pressed
}
12 голосов
/ 11 ноября 2011

Я принял решение, основанное частично на информации выше.Я просто устанавливаю 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;

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

11 голосов
/ 15 сентября 2010

Вы можете создать подкласс UIButton с именем MyButton и передать параметр по свойствам MyButton.

Затем получите параметр от отправителя (id).

3 голосов
/ 31 декабря 2014

Добавление скрытого titleLabel к параметру является лучшим решением.

Я сгенерировал массив arrUrl, который хранит NSURL файлов mov в моем альбоме телефона с помощью блока перечисления ресурсов.

Послеэто, я хватаюсь за Кадр, скажем, получить кадр в 3:00 секунды в файле фильма и сгенерировал файл изображения из кадра.

Далее, зациклите arrUrl и с помощью программы сгенерируйте кнопку с изображением в кнопке, добавьте кнопку к подпредставлению self.view.

Поскольку я должен передать URL фильмачтобы воспроизвести функцию Movie, я должен назначить button.titleLabel.text с одним URL-адресом фильма.и функция событий кнопки, получение URL-адреса из buttontitleLable.txt.

-(void)listVideos

{
   for(index=0;index<[self.arrUrl count];index++{
      UIButton *imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
      imageButton.frame = CGRectMake(20,50+60*index,50,50);

      NSURL *dUrl = [self.arrUrl objectAtIndex:index];

      [imageButton setImage:[[UIImage allow] initWithCGImage:*[self getFrameFromeVideo:dUrl]] forState:UIControlStateNormal];
      [imageButton addTarget:self action:@selector(playMovie:) forControlEvents:UIControlEventTouchUpInside];
      imageButton.titleLabel.text = [NSString strinfWithFormat:@"%@",dUrl];
      imageButton.titleLabel.hidden = YES;

      [self.view addSubView:imageButton];
   }
}

-(void)playMovie:(id) sender{
   UIButton *btn = (UIButton *)sender;
   NSURL *movUrl = [NSURL URLWithString:btn.titleLabel.text];
   moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:movUrl];
   [self presentMoviePlayerViewControllerAnimated:moviePlayer];
}

-(CGIImageRef *)getFrameFromVideo:(NSURL *)mUrl{
   AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:mUrl option:nil];
   AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
   generator.appliesPreferredTrackTransform = YES;
   NSError *error =nil;
   CMTime = CMTimeMake(3,1);
   CGImageRef imageRef = [generator copyCGImageAtTime:time actualTime:nil error:&error];
   if(error !=nil) {
      NSLog(@"%@",sekf,error);
   }

   return @imageRef;
}
1 голос
/ 03 марта 2017

tl; dr: Использовать блоки

Для Obj-C , например, есть CocoaPod SHControlBlocks , использование которого будет:

[self.btnFirst SH_addControlEvents:UIControlEventTouchDown withBlock:^(UIControl *sender) {
    [weakSelf performSegueWithIdentifier:@"second" sender:nil];
    NSLog(@"first");
  }];

Для Swift , мне нравится стручок Действия , который допускает блоки для UIControl s [1]:

// UIControl
let button = UIButton()
button.add(event: .touchUpInside) {
    print("Button tapped")
    playMusic(from: speakers_mp4, withSongAtPosition: indexPath.row)
}

Не то, чтобы кто-точитая 3-летнюю ветку.:: сверчки ::

[1] И UIView, UITextField, UIGestureRecognizer, UIBarButtonItem, Timer (формально NSTimer) и NotificationCenter (формально NSNotificationCenter).

1 голос
/ 12 сентября 2014

Вы можете установить тег кнопки и получить к нему доступ от отправителя в действии

[btnHome addTarget:self action:@selector(btnMenuClicked:)     forControlEvents:UIControlEventTouchUpInside];
                    btnHome.userInteractionEnabled = YES;
                    btnHome.tag = 123;

В вызываемой функции

-(void)btnMenuClicked:(id)sender
{
[sender tag];

    if ([sender tag] == 123) {
        // Do Anything
    }
}
1 голос
/ 15 сентября 2010

Я думаю, что правильный метод должен быть: - (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents

Справочник по UIControl

Откуда вы берете свой метод?

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

Ваш метод должен выглядеть следующим образом:

- (void)buttonPressed:(id)BUTTON_HERE { }

0 голосов
/ 21 декабря 2012

Чтобы добавить к Тристану ответ , кнопка также может получить (id)event в дополнение к (id)sender:

- (IBAction) buttonTouchUpInside:(id)sender forEvent:(id)event { .... }

Это может быть полезно, если, например, кнопка находится в ячейке в UITableView и вы хотите найти indexPath кнопки, к которой прикоснулись (хотя я полагаю, что это также можно найти с помощью элемента sender).

0 голосов
/ 31 июля 2011

У меня есть другое решение в некоторых случаях.

сохраните ваш параметр в скрытой UILabel. затем добавьте этот UILabel в качестве подпредставления UIButton.

при нажатии кнопки мы можем проверить все подпредставления UIButton. обычно только 2 UILabel в нем.

один - это заголовок UIButton, другой - тот, который вы только что добавили. прочитав это текстовое свойство UILabel, вы получите параметр.

Это относится только к текстовому параметру.

...