Highlighting a UIView similar to UIButton

Simple solution is override tap gesture regognizer like below:

Swift 4.x

class TapGestureRecognizer: UITapGestureRecognizer {
    var highlightOnTouch = true

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesBegan(touches, with: event)

        if highlightOnTouch {
            let bgcolor = view?.backgroundColor
            UIView.animate(withDuration: 0.1, delay: 0, options: [.allowUserInteraction, .curveLinear], animations: {
                self.view?.backgroundColor = .lightGray
            }) { (_) in
                UIView.animate(withDuration: 0.1, delay: 0, options: [.allowUserInteraction, .curveLinear], animations: {
                    self.view?.backgroundColor = bgcolor
                })
            }
        }
    }

}

setHighlighted isn't an animatable view property. Plus, you're saying two opposite things: you setHighlighted to YES and NO in the same breath. The result will be that nothing happens because there's no overall change.

Use the completion handler or delayed performance to change the highlight later.

EDIT:

You say "tried both but neither worked." Perhaps you need clarification on what I mean by delayed performance. I just tried this and it works perfectly:

- (void) tapped: (UIGestureRecognizer*) g {
    label.highlighted = YES;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        label.highlighted = NO;
    });
}

The label must have a different textColor vs its highlightedTextColor so that something visible happens.


Swift 4

You can use a custom view like this for example:

class HighlightView: UIView {

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        DispatchQueue.main.async {
            self.alpha = 1.0
            UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveLinear, animations: {
                self.alpha = 0.5
            }, completion: nil)
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        DispatchQueue.main.async {
            self.alpha = 0.5
            UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveLinear, animations: {
                self.alpha = 1.0
            }, completion: nil)
        }
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        DispatchQueue.main.async {
            self.alpha = 0.5
            UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveLinear, animations: {
                self.alpha = 1.0
            }, completion: nil)
        }
    }
}

Just play around with the duration and animations as you like. In the end you can use it instead of UIView and whenever you will click on it, it will change its alpha value so it will look like a highlight.