Corrige o destaque do botão UIB / cintilação da imagem selecionada

Se você tiver um UIButton que usa a mesma imagem para UIControlStateSelected e UIControlStateHighlighted, provavelmente notou que as imagens tremem quando o botão é tocado rapidamente. O UIKit trata o estado do botão como um sinalizador de bit enumerado, portanto, durante um evento de toque rápido, o botão existe em um estado em que é selecionado e destacado.

Para corrigir a cintilação, o UIButton precisa ter a imagem definida para o estado UIControlStateSelected | UIControlStateHighlighted.

UIImage *sl = [self imageForState:UIControlStateSelected];
[aButton setImage:sl forState:(UIControlStateSelected | UIControlStateHighlighted)];

Para aplicar esta correção a todos os UIButtons carregados de arquivos NIB, crie uma nova categoria UIButton contendo os seguintes métodos.

void UIButtonAwakeFromNibSwizzle() {
Class c = [UIButton class];
SEL orig
= @selector(awakeFromNib);
SEL
new = @selector(fixedAwakeFromNib);

Method origMethod = class_getInstanceMethod(c, orig);
Method newMethod = class_getInstanceMethod(c, new);
if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
class_replaceMethod
(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
else
method_exchangeImplementations
(origMethod, newMethod);
}

- (void)fixedAwakeFromNib {
// swizzled functions get exchanged, so calling fixedAwakeFromNib calls the original function
[self fixedAwakeFromNib];

UIImage *hl = [self imageForState:UIControlStateHighlighted];
UIImage *sl = [self imageForState:UIControlStateSelected];
if (hl == sl) {
[self setImage:hl forState:(UIControlStateSelected | UIControlStateHighlighted)];
}
}

Agora, se você chamar UIButtonAwakeFromNibSwizzle () em didFinishLaunchingWithOptions do Delegado do Aplicativo, fixedAwakeFromNib será chamado sempre que um UIButton chamar awakeFromNib.