Pasar parámetros en la acción del botón: @selector

Quiero pasar la URL de la película desde mi botón generado dinámicamente a MediaPlayer:

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

pero action:@selector() withObject: ¿no funciona?

hay alguna otra solucion?

¡Gracias por la ayuda!

    Editar. Encontrado de una manera más ordenada!

    Un argumento que el botón puede recibir es (id)sender . Esto significa que puede crear un nuevo botón, heredando de UIButton, que le permite almacenar los otros argumentos previstos. Con suerte, estos dos fragmentos ilustran qué hacer.

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

    y

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

    Esta fue mi sugerencia original.

    Hay una forma de lograr el mismo resultado, pero no es bonita. Supongamos que desea agregar un parámetro a su método de navigate . El siguiente código no le permitirá pasar ese parámetro para navigate .

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

    Para evitar esto, puede mover el method navegación a una clase propia y establecer los “parámetros” como atributos de esa clase …

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

    Por supuesto, puede mantener el método de navegación en la clase original y hacer que NavAid lo invoque, siempre que sepa dónde encontrarlo.

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

    Como dije, no es bonita, pero funcionó para mí y no he encontrado a nadie que sugiera ninguna otra solución de trabajo.

    Encontré solución. La llamada:

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

    Y aquí el método llamado:

     -(void) buttonPressed : (id) sender{ UIButton *clicked = (UIButton *) sender; NSLog(@"%d",clicked.tag);//Here you know which button has pressed } 

    Puede subclase un UIButton llamado MyButton y pasar el parámetro por las propiedades de MyButton.

    Luego, recupera el parámetro del remitente (id).

    Hice una solución basada en parte por la información anterior. Acabo de establecer el título Label . texto a la cadena que quiero pasar, y establecer el titleLabel.hidden = YES

    Me gusta esto :

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

    De esta manera, no hay necesidad de una herencia o categoría y no hay pérdida de memoria

    Agregar el título oculto Label al parámetro es la mejor solución.

    Genere un array arrUrl que almacena el NSURL de los archivos mov en el álbum de mi teléfono mediante el bloque enumerate assets.

    Después de eso, tomo Frame, digamos, obtengo el fotogtwig a 3:00 segundos en el archivo de película y genero el archivo de imagen desde el fotogtwig.

    A continuación, recorra el campo y utilice el progtwig Genere el botón con la imagen en el botón, agregue el botón a la subvista de la vista propia.

    Debido a que tengo que pasar la película Url a la función reproducirMovie, tengo que asignar el botón.titleLabel.text con una URL de película. y la función de eventos del botón, recupera la url de 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; } 

    Creo que el método correcto debería ser: - (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents

    Referencia UIControl

    ¿De dónde obtienes tu método?

    Veo que su selector tiene un argumento, ese argumento será llenado por el sistema de tiempo de ejecución. Le devolverá el botón a través de ese argumento.

    Su método debe verse así:

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

    Puede establecer la etiqueta del botón y acceder desde el remitente en acción

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

    En la función llamada

     -(void)btnMenuClicked:(id)sender { [sender tag]; if ([sender tag] == 123) { // Do Anything } } 

    tl; dr: Usar bloques

    Para Obj-C , por ejemplo, hay un CocoaPod SHControlBlocks , cuyo uso sería:

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

    Para Swift , me encantan las acciones de pod, que permiten bloques para UIControl s [1]:

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

    No es que alguien esté leyendo un hilo de 3 años. :: grillos ::

    [1] Y UIView , UITextField , UIGestureRecognizer , UIBarButtonItem , Timer (formalmente NSTimer) y NotificationCenter (formalmente NSNotificationCenter).

    UIButton responde a addTarget: action: forControlEvents: ya que hereda de UIControl. Pero no responde a addTarget: action: withObject: forControlEvents:

    ver referencia para el método y para UIButton

    Podría extender UIButton con una categoría para implementar ese método, pensó.

    Tengo otra solución en algunos casos.

    almacena tu parámetro en un UILabel oculto. luego agregue este UILabel como subvista de UIButton.

    cuando se hace clic en el botón, podemos verificar todas las subvistas de UIButton. normalmente solo 2 UILabel en él.

    uno es el título de UIButton, el otro es el que acaba de agregar. lee esa propiedad de texto de UILabel, obtendrás el parámetro.

    Esto solo aplica para el parámetro de texto.

    Para agregar a la respuesta de Tristan , el botón también puede recibir el (id)event (id)sender :

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

    Esto puede ser útil si, por ejemplo, el botón está en una celda en una UITableView y desea encontrar el indexPath de indexPath del botón que se tocó (aunque supongo que esto también se puede encontrar a través del elemento sender ).