Передача параметров на действие кнопки: @selector
Я хочу передать URL-адрес фильма из моей динамически сгенерированной кнопки в MediaPlayer:
[button addTarget:self action:@selector(buttonPressed:) withObject:[speakers_mp4 objectAtIndex:[indexPath row]] forControlEvents:UIControlEventTouchUpInside];
но action:@selector() withObject:
не работает?
Есть ли другое решение?
Спасибо за помощь!
Ответы
Ответ 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).