Detecting Touches on a Label Control

The UILabel control is useful for displaying information, but it does not recognize events: an IBAction method cannot be wired to it. So how do we detect a touch event on a label and respond to it? The answer lies in the UITapGestureRecognizer object. Let’s see how it works.

Start Xcode, select “Create a new Xcode project,” and click Next. Choose the Single View Application template, and click Next. Name the project ControlTouch, and select options as shown:

Click Next, choose a location to save the project, and click Create.

When the project has been created, select the ViewController.h file, and add two properties and a method as shown here:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (nonatomic, strong) IBOutlet UILabel *output;
@property (nonatomic, strong) IBOutlet UILabel *touchLabel;

(IBAction)viewWasTouched:(UITapGestureRecognizer *)sender;

@end

Select the ViewController.xib file, and add two labels to the view. Change the text of the first label to “” (an empty string) and the text of the second label to “Touch Here.” When you are finished, the view should look something like this:

The View. The top label is selected, with its text deleted.

Now drag a UITapGestureRecognizer object from the library to the view. Wire up the two labels (output is wired to the top label with the empty text), then wire the viewWasTouched: method to the UITapGestureRecognizer.

Open the ViewController.m file, and add the following immediately after the @implementation line:

@synthesize output, touchLabel;

(IBAction)viewWasTouched:(UITapGestureRecognizer *)sender
{
    if (sender.numberOfTouches == 1) {
        CGPoint touchPoint = [sender locationOfTouch:0 inView:self.touchLabel];
        CGFloat touchX = touchPoint.x;
        CGFloat touchY = touchPoint.y;
        // is the touch in the bounds of the touchLabel?
        if (touchX >= 0 && touchY >= 0) {
            if (touchX <= self.touchLabel.bounds.size.width && touchY <= self.touchLabel.bounds.size.height) {
                [self performSelector:@selector(labelTouched)];
            }
        }        
    }
}

// listing continues… webmaster: the labelTouched method goes here, delete this line

(void)labelTouched
{
    if ([self.output.text isEqualToString:@""]) {
        self.output.text = @"Label Touched!";
    } else {
        self.output.text = @"";
    }
}

As always, we first synthesize the properties. In the viewWasTouched method, we verify that the number of touches is one, then we see if the touch occurred within the bounds of the touchLabel.

UITapGestureRecognizer recognizes taps at the view level. But we can get the position of the touch within the context of any view (not just the main view). In this example, we get the location in the context of the touchLabel control, and verify that the touch point is not less than (0, 0) (the top left coordinate of the label), or greater than the label’s width and height.

At this point, we’ve detected a touch, and verified that the location of the touch is inside the bounds of the label. We could put code directly inside this if statement, but it’s cleaner to place the code that handles the touch event inside a separate method. We can then tell the view to call that message by sending it the performSelector message.

The labelTouched method simply toggles the text of the output label between @”Label Touched” and @””. When we run the app, each time we touch the “Touch Here” label, the text in the output label will change.

This technique will work for any control not having built – in touch based events. For example, we could detect and respond to touches in a UITextField or UITextView control if we want perform some action in addition to the default action of displaying the keyboard.

Leave a Reply

Your email address will not be published. Required fields are marked *