[Objective-C] Recognize letter pressed on UILabel

You have an UILabel and want to know which letter was pressed on touch.

From a question on stackoverflow, I’ve implemented in this fast and stupid way.

Solution

1) Subclass UILabel, and add a touchesEnded: to recognize touches on your label.
2) Store in an array all the sizes of the letters using system method sizeWithFont:
3) Get the touch point and compare with the letters size.
Done!

Create an UILabel subclass

[code lang=”java” autolinks=”false” collapse=”false” firstline=”1″ gutter=”true” htmlscript=”false” light=”false” padlinenumbers=”false” smarttabs=”true” tabsize=”4″ toolbar=”false”]//
// APLabel.h
//
#import <uikit/UIKit.h>

@protocol APLabelDelegate &lt;nsobject&gt;
@required
– (void) didLetterFound:(char)letter;
@end

@interface APLabel : UILabel
@property (nonatomic, assign) id &lt;aplabeldelegate&gt; delegate;
@end[/code]

[code lang=”java” autolinks=”false” collapse=”false” firstline=”1″ gutter=”true” htmlscript=”false” light=”false” padlinenumbers=”false” smarttabs=”true” tabsize=”4″ toolbar=”false”]//
// APLabel.m
//
#import "APLabel.h"

@implementation APLabel

– (id)initWithCoder:(NSCoder *)aDecoder
{
if ( self = [super initWithCoder:aDecoder])
{
self.backgroundColor          = [UIColor greenColor];
self.userInteractionEnabled   = YES;
}
return self;
}

– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[touches allObjects] objectAtIndex:0];
CGPoint pos    = [touch locationInView:self];

int sizes[self.text.length];
for ( int i=0; i&lt;self .text.length; i++ )
{
char letter         = [self.text characterAtIndex:i];
NSString *letterStr = [NSString stringWithFormat:@"%c", letter];

CGSize letterSize   = [letterStr sizeWithFont:self.font];
sizes[i]            = letterSize.width;
}

int sum = 0;
for ( int i=0; i&lt;self.text.length; i++)
{
sum += sizes[i];
if ( sum &gt;= pos.x )
{
[ _delegate didLetterFound:[ self.text characterAtIndex:i] ];
return;
}
}
}
@end[/code]

Next, from Interface Builder, create an UILabel and change the class with APLabel, like this:
Schermata 2013-09-11 alle 11.26.59

On your ViewController, add the APLabelDelegate and the IBOutlets

[code lang=”java” autolinks=”false” collapse=”false” firstline=”1″ gutter=”true” htmlscript=”false” light=”false” padlinenumbers=”false” smarttabs=”true” tabsize=”4″ toolbar=”false”]@interface APViewController : UIViewController <APLabelDelegate>
{
IBOutlet UILabel *_LetterFound;
IBOutlet APLabel *_myLabel;
}
@end[/code]

In your implementation, set the delegate and implement it:

[code lang=”java” autolinks=”false” collapse=”false” firstline=”1″ gutter=”true” htmlscript=”false” light=”false” padlinenumbers=”false” smarttabs=”true” tabsize=”4″ toolbar=”false”]#import "APViewController.h"

@implementation APViewController
– (void)viewDidLoad
{
[super viewDidLoad];
_myLabel.delegate = self;
}

– (void)didLetterFound:(char)letter
{
_LetterFound.text = [NSString stringWithFormat:@"%c", letter];
}
@end[/code]

Connect everything, build, run and click letters!

Schermata 2013-09-11 alle 11.14.25

Have fun.

 

Alberto Pasca

Software engineer @ Pirelli & C. S.p.A. with a strong passion for mobile  development, security, and connected things.