31

Does anyone have any sample code for detecting touches on a dynamically created UIView? I have found some references to touchesBegan but cannot figure out how to implement it...

darklon
  • 468
  • 3
  • 13
Andrew M
  • 4,208
  • 11
  • 42
  • 67

6 Answers6

84

A very general way to get touches is to override these methods in a custom UIView subclass:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

The official docs for these methods is under Responding to Touch Events in the UIResponder class docs (UIView inherits those methods since it's a subclass of UIResponder). Longer and more introductory docs can be found in the Event Handling Guide for iOS.

If you just want to detect a tap (touch-down, then touch-up within your view), it's easiest to add a UIButton as a subview of your view, and add your own custom method as a target/action pair for that button. Custom buttons are invisible by default, so it wouldn't affect the look of your view.

If you're looking for more advanced interactions, it's also good to know about the UIGestureRecognizer class.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Tyler
  • 28,498
  • 11
  • 90
  • 106
16

Create touch event with UIAnimation on UIView , you can manage touches on UIView anywhere .

Following Code : here self.finalScore is a UIView , and cup is a UIImageView . I handle

the touch event on UIImageView , it present inside the UIView .

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

UITouch *touch1 = [touches anyObject];
CGPoint touchLocation = [touch1 locationInView:self.finalScore];
CGRect startRect = [[[cup layer] presentationLayer] frame];
CGRectContainsPoint(startRect, touchLocation);

[UIView animateWithDuration:0.7 
                      delay:0.0 
                    options:UIViewAnimationCurveEaseOut 
                 animations:^{cup.transform = CGAffineTransformMakeScale(1.25, 0.75);} 
                 completion:^(BOOL finished) {  
                     [UIView animateWithDuration:2.0 
                                           delay:2.0 
                                         options:0
                                      animations:^{cup.alpha = 0.0;} 
                                      completion:^(BOOL finished) {
                                          [cup removeFromSuperview];
                                          cup = nil;}];                 
                 }];

}

Like UITapGestureRecognizer is another way of handle the touch events on UIView ....

UITapGestureRecognizer *touchOnView = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(releaseButAction)] autorelease];

// Set required taps and number of touches
[touchOnView setNumberOfTapsRequired:1];
[touchOnView setNumberOfTouchesRequired:1];

// Add the gesture to the view
[[self view] addGestureRecognizer:touchOnView];
itsji10dra
  • 4,603
  • 3
  • 39
  • 59
Arunjack
  • 621
  • 1
  • 6
  • 4
  • the second code snipped helped me, but better practice would be `UITapGestureRecognizer *touchOnView = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(releaseButAction:)] autorelease];` and the method would then be `- (void)releaseButAction:(UIGestureRecognizer *)gestureRecognizer`.. just fyi! – sixstatesaway Jan 09 '13 at 10:13
5

Create your own custom UIView from a subclass you created by inheriting UIView and override the following method inside the sub-class,

(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

}
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
ThE uSeFuL
  • 1,456
  • 1
  • 16
  • 29
4

With gesture recognizer, it is much easy to catch touch events.

Find one guested from component library in storyboard:

enter image description here

For example, drag Tap Gesture Recognizer to your view. It is not shown in the view UI. You can find it from Document outline in the left panel in Storyboard:

enter image description here

The final step is to link it (by control-drag) to the view as delegate where touch is monitored, and control-drag to your view controller class as an action. Here is the picture of link connections.

enter image description here

and action code:

@IBAction func tapAction(_ sender: Any) {
    // touch is captured here.
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
David.Chu.ca
  • 37,408
  • 63
  • 148
  • 190
2

Instead of capturing touch using gesture, I would suggest to change UIView parent class to UIControl, so that it can handle touchUpInside event

From:

@interface MyView : UIView

To:

@interface MyView : UIControl

and then add this line for view-

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

Because gesture may create problem while scrolling.

Zoeb S
  • 695
  • 1
  • 7
  • 21
1

My method is simply change the UIView to UIControl class in InterfaceBuilder IdentityInspector, then the ConnectionsInspector will instantly have the touch event ready for hook.

zero code changes.

DazChong
  • 3,513
  • 27
  • 23