Reputation: 40991
I have a UITextView
that I want to detect a single tap for.
It looks like I would be fine with simply overriding touchesEnded:withEvent
and checking [[touches anyObject] tapCount] == 1
, however this event doesn't even fire.
If I override the 4 events like this:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
NSLog(@"touchesBegan (tapCount:%d)", touch.tapCount);
[super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touches moved");
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
NSLog(@"touchesEnded (tapCount:%d)", touch.tapCount);
[super touchesEnded:touches withEvent:event];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touches cancelled");
}
I get output like this:
> touchesBegan (tapCount:1)
> touchesCancelled
> touchesBegan (tapCount:1)
> touches moved
> touches moved
> touches moved
> touchesCancelled
It seems I never get the touchesEnded
event.
Any ideas?
Upvotes: 4
Views: 7966
Reputation: 40991
Update: I ended up using the technique here: https://devforums.apple.com/message/94569#94569
I'm not sure if this is a bug or not, but the UITextView does need to utilize the touch events to do the popup menu for copy & paste for 3.0, so that might explain why it swallows this event.
Pretty lame if you ask me.
Update: I blogged about this here: http://benscheirman.com/2009/07/detecting-a-tap-on-a-uitextview
Upvotes: 1
Reputation: 362
I subclassed UITextview like so, which seems to work, even with IOS 5.0.1. The key is to override touchesBegan as well, not just touchesEnded (which is what I'm really interested in).
@implementation MyTextView
- (id)initWithFrame:(CGRect)frame {
return [super initWithFrame:frame];
}
- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event {
// If not dragging, send event to next responder
if (!self.dragging)
[self.nextResponder touchesBegan: touches withEvent:event];
else
[super touchesBegan: touches withEvent: event];
}
- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event {
// If not dragging, send event to next responder
if (!self.dragging)
[self.nextResponder touchesEnded: touches withEvent:event];
else
[super touchesEnded: touches withEvent: event];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == @selector(paste:))
return NO;
if (action == @selector(copy:))
return NO;
if (action == @selector(cut:))
return NO;
if (action == @selector(select:))
return NO;
if (action == @selector(selectAll:))
return NO;
return [super canPerformAction:action withSender:sender];
}
- (BOOL)canBecomeFirstResponder {
return NO;
}
- (void)dealloc {
[super dealloc];
}
Upvotes: 1
Reputation: 5654
You can turn off Cut/Copy/Paste by overriding the canPerformAction:withSender:
method, so you could just return NO for all the actions you don't want to permit.
See the UIResponder documentation...
Hopefully that will stop your touches from being eaten.
Upvotes: 0