Передача параметров на действие кнопки: @selector - программирование
Подтвердить что ты не робот

Передача параметров на действие кнопки: @selector

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

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

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

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

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

4b9b3361

Ответ 1

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

Один аргумент, который может получить кнопка, - (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];

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

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

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

Ответ 2

Я нашел решение. Вызов:

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

Ответ 3

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

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

Ответ 4

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

Вот так:

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

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

Ответ 5

Добавить скрытый заголовокLabel в параметр - лучшее решение.

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

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

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

Поскольку мне нужно передать фильм Url для функции playMovie, мне нужно назначить 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;
}

Ответ 6

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

Ссылка UIControl

Откуда вы получаете свой метод?

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

Ваш метод должен выглядеть так:

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

Ответ 7

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

[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
    }
}

Ответ 8

UIButton отвечает на addTarget: action: forControlEvents: поскольку он наследует UIControl. Но он не отвечает на addTarget: action: withObject: forControlEvents:

см. ссылка для метода и UIButton

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

Ответ 9

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

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

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

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

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

Ответ 10

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

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

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

Ответ 11

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

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

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

Для Swift мне нравится pod Actions, который позволяет блоки для UIControl [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).