I have a UIView
instance that I am animating using CAKeyframeAnimation
. It is a looping animation and will be constantly in motion. However, I need to allow user interaction with the item (responding to taps, to be exact). Because CoreAnimation is only moving the presentation layer and not the model, I cannot use a UIButton
instance, for example, to essentially get the touchUpInside
events.
Consider the following basic example layout:
I am using the blue box for touch events by overriding the touchesEnded:withEvent:
method on a UIView
subclass. I am then bubbling that event through an NSNotification
(I really don't want to introduce a lot of coupling to handle this event) to the containing view controller, which then does a hitTest:
on the red box being animated.
All of this seems rather hacky to just be able to touch an animated UIView
. What are some of the best patterns for handling touches for animated UIView
/CALayer
instances?
Tracking the touch in the superview is correct I believe. But I would do hit testing in the superview rather than posting a notification to the view controller. Something like this:
Create a MYAnimationContainerView
class (the blue box).
Give it a delegate or block callback that the owning view controller sets. For example:
__weak id weakSelf = self;
MYAnimationContainerView *view = [[MYAnimationContainerView alloc] initWithTouchCallback:^(UIView *touchedView){
[weakSelf handleTouchToView:touchedView];
}];
In MYAnimationContainerView
, override both touchesBegan:withEvent:
and touchesEnded:withEvent:
. In began
, perform a hit test on the presentation layer of the moving view(s). Keep track of which one (if any) was touched. In ended
, perform another hit test. If it's the same view, then call your callback.
The above could just as easily be implemented with a delegate
protocol rather than a block. I've just been getting in the habit of preferring blocks over one-method delegate protocols.
You could also implement it with target/selector, but that pattern has gotten to be a bit of a hassle with ARC, and I tend to discourage its use today.