Mantener un UIButton seleccionado después de un toque

Después de que mi usuario haga clic en un botón, me gustaría que ese botón permanezca presionado durante el tiempo que realice una operación de red. Cuando se completa la operación de red, quiero que el botón vuelva a su estado predeterminado.

Intenté llamar – [UIButton setSelected:YES] justo después de presionar el botón (con una llamada correspondiente a – [UIButton setSelected:NO] después de que termine mi [UIButton setSelected:NO] red) pero parece que no hace nada. Lo mismo si llamo a setHighlighted:

Supongo que podría intentar cambiar la imagen de fondo para indicar un estado seleccionado mientras dure la operación de red, pero eso parece un truco. ¿Alguna mejor sugerencia?

Así es como se ve mi código:

 - (IBAction)checkInButtonPushed { self.checkInButton.enabled = NO; self.checkInButton.selected = YES; self.checkInButton.highlighted = YES; [self.checkInActivityIndicatorView startAnimating]; [CheckInOperation startWithPlace:self.place delegate:self]; } - (void)checkInCompletedWithNewFeedItem:(FeedItem*)newFeedItem wasNewPlace:(BOOL)newPlace possibleError:(NSError*)error; { [self.checkInActivityIndicatorView stopAnimating]; self.checkInButton.enabled = YES; self.checkInButton.selected = NO; self.checkInButton.highlighted = NO; } 

¿Cómo está configurando las imágenes para los diferentes UIControlStates en el botón? ¿Está configurando una imagen de fondo para UIControlStateHighlighted y UIControlStateSelected ?

 UIImage *someImage = [UIImage imageNamed:@"SomeResource.png"]; [button setBackgroundImage:someImage forState:UIControlStateHighlighted]; [button setBackgroundImage:someImage forState:UIControlStateSelected]; 

Si está configurando el estado seleccionado en el evento de tocar el botón en lugar de retocar en el interior, su botón estará realmente en un estado resaltado + seleccionado, por lo que también querrá configurarlo.

 [button setBackgroundImage:someImage forState:(UIControlStateHighlighted|UIControlStateSelected)]; 

Editar:

Para resumir mis comentarios en los comentarios y para abordar el código que publicó … debe establecer sus imágenes de fondo para el estado completo de UIControl que se encuentra. De acuerdo con su fragmento de código, este estado de control estaría deshabilitado + seleccionado + resaltado por la duración de la operación de la red. Esto significa que deberías hacer esto:

 [button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateHighlighted|UIControlStateSelected)]; 

Si elimina el highlighted = YES , entonces necesitaría esto:

 [button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateSelected)]; 

¿Obtener la imagen?

Tengo una manera más fácil. Simplemente use “performSelector” con 0 delay para realizar [button setHighlighted:YES] . Esto realizará un re-resaltado después de que termine el runloop actual.

 - (IBAction)buttonSelected:(UIButton*)sender { NSLog(@"selected %@",sender.titleLabel.text); [self performSelector:@selector(doHighlight:) withObject:sender afterDelay:0]; } - (void)doHighlight:(UIButton*)b { [b setHighlighted:YES]; } 

“Todo mejora cuando enciendes el poder”

  button.selected = !button.selected; 

funciona perfectamente … después de conectar la salida al botón en el Interface Builder.

No es necesario configurarBackgroundImage: forState :, el constructor le permite especificar el fondo (se redimensiona si es necesario) o las imágenes en primer plano (sin cambiar el tamaño).

Intenta usar NSOperationQueue para lograr esto. Pruebe el código de la siguiente manera:

 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ theButton.highlighted = YES; }]; 

Espero que esto ayude.

Usa un bloque para que no tengas que construir un método completamente diferente:

 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{ theButton.highlighted = YES; }); 

Actualizar

Para que quede claro, aún necesita establecer el fondo (o la imagen normal) para los estados de combinación, así como los regulares, como dice Sbrocket en la respuesta aceptada. En algún momento, su botón estará seleccionado y resaltado, y no tendrá una imagen para eso a menos que haga algo como esto:

 [button setBackgroundImage:someImage forState (UIControlStateHighlighted|UIControlStateSelected)]; 

De lo contrario, su botón puede retroceder a la imagen UIControlStateNormal para el breve estado seleccionado + resaltado y verá un flash.

Rápidamente lo hago como lo siguiente.

UIButton una Subclase de UIButton e implementé un state propiedad personalizado

 class ActiveButton: UIButton { private var _active = false var active:Bool { set{ _active = newValue updateState() } get{ return _active } } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.addTarget(self, action: #selector(ActiveButton.touchUpInside(_:)), forControlEvents: .TouchUpInside) } func touchUpInside(sender:UIButton) { active = !active } private func updateState() { NSOperationQueue.mainQueue().addOperationWithBlock { self.highlighted = self.active } } } 

Funciona perfectamente para mi

Tuve un problema similar en el que quería un botón para mantenerlo resaltado después de hacer clic. El problema es si intenta usar setHighlighted:YES dentro de la acción de hacer clic se restablecerá justo después de hacer clic en la acción, - (IBAction)checkInButtonPushed

Lo resolví usando un NSTimer como este

 NSTimer *timer; timer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector: @selector(selectCurrentIndex) userInfo: nil repeats: NO]; 

y luego llamar a setHighlighted:YES desde mi método selectCurrentIndex . Yo uso los botones UIButtonTypeRoundedRect regulares.

Tengo otra forma … si no quieres usar imágenes, y quieres el efecto de un botón presionado, puedes subclasificar el Botón y aquí está mi código:

en el archivo .h:

 @interface reservasButton : UIButton { BOOL isPressed; } @end 

En el archivo .m:

 #import  @implementation reservasButton -(void)setupView { //This is for Shadow self.layer.shadowColor = [UIColor blackColor].CGColor; self.layer.shadowOpacity = 0.5; self.layer.shadowRadius = 1; self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f); //comment // self.layer.borderWidth = 1; self.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; // [self setBackgroundColor:[UIColor whiteColor]]; // self.opaque = YES; } -(id)initWithFrame:(CGRect)frame{ if((self = [super initWithFrame:frame])){ [self setupView]; } return self; } -(id)initWithCoder:(NSCoder *)aDecoder{ if((self = [super initWithCoder:aDecoder])){ [self setupView]; } return self; } //Here is the important code -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ if (isPressed == FALSE) { self.contentEdgeInsets = UIEdgeInsetsMake(1.0,1.0,-1.0,-1.0); self.layer.shadowOffset = CGSizeMake(1.0f, 1.0f); self.layer.shadowOpacity = 0.8; [super touchesBegan:touches withEvent:event]; isPressed = TRUE; } else { self.contentEdgeInsets = UIEdgeInsetsMake(0.0,0.0,0.0,0.0); self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f); self.layer.shadowOpacity = 0.5; [super touchesEnded:touches withEvent:event]; isPressed = FALSE; } } ` 

Aquí hay una implementación de C # / MonoTouch (Xamarin.iOS) utilizando los enfoques presentados anteriormente. Asume que ya ha establecido el estado de imagen resaltada y configura los estados seleccionados y seleccionados para usar la misma imagen.

 var selected = button.BackgroundImageForState(UIControlState.Highlighted); button.SetBackgroundImage(selected, UIControlState.Selected); button.SetBackgroundImage(selected, UIControlState.Selected | UIControlState.Highlighted); button.TouchUpInside += delegate { NSTimer.CreateScheduledTimer(TimeSpan.FromMilliseconds(0), delegate { button.Highlighted = true; NSTimer.CreateScheduledTimer(TimeSpan.FromMilliseconds(200), delegate { button.Highlighted = false; }); }); };