Advertise Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

sdkIQ for iPhone
($4.99)

Your First iPhone App
($1.99)

iPhone Code Generator
($9.99)

Dual Matches
($0.99)

Calcuccino Programmers' Calculator
($2.99)

SDKtoday
(free)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 09-09-2008, 02:37 PM   #1 (permalink)
New Member
 
Join Date: Aug 2008
Posts: 17
Default Tap & Double Tap.

Hi,

I know that a lot of threads are opend for this problem but yet, I haven't found a solution for this problem.

Code:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
	
	// We only support single touches, so anyObject retrieves just that touch from touches
	UITouch *touch = [[event allTouches] anyObject];

	if ([touch tapCount] == 2) {
		//Do A
	}
	
	// In case of a double tap outside the placard view, update the placard's display string
	else if ([touch tapCount] == 1) {
		//DO B
		
	}
}
The problem is, if i double tap, the B function is executed also.
I found this thread:
Single touch event always get fired with double touch

and he said there that this is the behavior... what does he means ?

95% of all the posts use the 'tapCount'.


I've even try to use:
UIControlEventTouchDownRepeat & UIControlEventTouchUpInside, with IBActions, and always the UIControlEventTouchUpInside call first...

How do i handle ONLY double tap ?


Thanks.
eitangabay is offline   Reply With Quote
Old 09-09-2008, 10:43 PM   #2 (permalink)
Registered Member
 
tkilmer's Avatar
 
Join Date: May 2008
Posts: 583
Default

I personally add a BOOL. I make it something like tappedTwice. I set it equal to YES once I enter the double count and I set up the single count to not run if tappedTwice is equal to YES. I have the value reset to NO once I know I can again. Without looking at my code, this is how I do it:
Code:
 BOOL tappedTwice = NO;
if ([touch tapCount] == 2) {
tappedTwice = YES;
//whatever here
}
else if ([touch tapCount] == 1 && !tappedTwice) {

//whatever here
}
}
If it is setup as a local BOOL, then you do not have to worry about setting it back to NO. This works for me, hope it works for you.
tkilmer is offline   Reply With Quote
Old 09-10-2008, 12:44 AM   #3 (permalink)
New Member
 
Join Date: Aug 2008
Posts: 17
Default Thanks

Thanks I'll try it, it's sounds good.

But, if i need to handle both of the taps .... ?

tapOnce doing A, and tapTwice doing B.
eitangabay is offline   Reply With Quote
Old 09-10-2008, 07:16 AM   #4 (permalink)
New Member
 
Join Date: Apr 2008
Posts: 420
Send a message via AIM to jeff_lamarche Send a message via Yahoo to jeff_lamarche
Default

Setting a boolean is a bit kludgey, and will be hard to maintain for other tap situations (triple, quadruple, etc). There actually IS an "official" way to handle this situation described in the documentation. It's described, but Apple does not give sample code.

How you handle it is to call the correct method in each case using performSelector:withObject:afterDelay:, then, in each situation except single-tap, cancel the previous call before it executes (double-tap cancels the single-tap call, triple-tap cancels the double-tap call). This is what it might look like:


Code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
	UITouch *touch = [touches anyObject];
	NSUInteger tapCount = [touch tapCount];
	
	switch (tapCount) {
		case 1:
			[self performSelector:@selector(singleTapMethod) withObject:nil afterDelay:.4];
			break;
		case 2:
			[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTapMethod) object:nil];
			[self performSelector:@selector(doubleTapMethod) withObject:nil afterDelay:.4];
			break;
		case 3:
			[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(doubleTapMethod) object:nil];
			[self performSelector:@selector(tripleTapMethod) withObject:nil afterDelay:.4];
			break;
		case 4:
			[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(tripleTapMethod) object:nil];
			[self quadrupleTap];
			break;
		default:
			break;
	}

}
@end
__________________
Check out my iPhone Dev Blog
You can send me e-mail at my forum username at mac dot com.
jeff_lamarche is offline   Reply With Quote
Old 09-10-2008, 07:49 AM   #5 (permalink)
New Member
 
Join Date: Aug 2008
Posts: 17
Default Ya

Thanks for you answer.

I just finish reading this section about the performSelector and the cancelPreviousPerformRequestsWithTarget in the iPhone OS Programing...

That's looking good, have you try it yet?
eitangabay is offline   Reply With Quote
Old 09-10-2008, 07:50 AM   #6 (permalink)
New Member
 
Join Date: Apr 2008
Posts: 420
Send a message via AIM to jeff_lamarche Send a message via Yahoo to jeff_lamarche
Default

Yes, that code I pasted comes from a working sample application written for a book on the iPhone (which can't be published until the NDA drops ).
__________________
Check out my iPhone Dev Blog
You can send me e-mail at my forum username at mac dot com.
jeff_lamarche is offline   Reply With Quote
Old 09-10-2008, 07:58 AM   #7 (permalink)
New Member
 
Join Date: Aug 2008
Posts: 17
Default Great.

iPhone developer book, by developer (and a good one... ) - Great !

I'll be more then happy to be updated on the book release.

Thanks for your help.

Eitan.
eitangabay is offline   Reply With Quote
Old 10-23-2008, 09:20 PM   #8 (permalink)
New Member
 
Join Date: Sep 2008
Posts: 2
Default

Thank you. I can confirm that the multi-tapping works well
meonfire is offline   Reply With Quote
Old 03-04-2009, 04:46 AM   #9 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 19
Default Thanks

Thanks for providing the solution for this problem!!!!
sanniv is offline   Reply With Quote
Old 06-21-2009, 01:13 AM   #10 (permalink)
Registered Member
 
Join Date: Feb 2009
Posts: 50
Default

That sounds great but I want to be able to send the event and the touch to the singleTap method since this will forward it if necessary to another responder. I cannot do this with this solution.


I have tried using a timer but there seems to be a problem. Can anybody tell me what might be wrong.

In my touchesBegan method I did
Code:
	if ([doubleTapTimer isValid]) {
		[doubleTapTimer invalidate];
		doubleTapTimer = nil;
	}
	if(![doubleTapTimer isValid]) {
		[self startTouchTimer:DOUBLE_TAP_TIMER withTouch:touches andEvent:event];
	} else if (tapCount == 2) {
		if(self.zoomedView) {
			[self resetScrollZoom];
		} else {
			[super touchesBegan:touches withEvent:event];
		}
		[doubleTapTimer invalidate];
		doubleTapTimer = nil;
		return;
	}
Then in my startTouchTimer method I prepare my timer with an invocation to call the singleTapMethod.

Code:
//Prepare invocation
	SEL singleTapSelector = @selector(singleTapDone:withEvent:);  //selector
	NSMethodSignature * sig = [[self class] instanceMethodSignatureForSelector:singleTapSelector]; //signature to initialize
	NSInvocation *singleTapObjects = [NSInvocation invocationWithMethodSignature:sig]; //initialize selector
	[singleTapObjects setTarget:self];
	[singleTapObjects setSelector:singleTapSelector];
	[singleTapObjects setArgument:&touches atIndex:2];		//set parameters for invocations
	[singleTapObjects setArgument:&event atIndex:3];
	
	
	doubleTapTimer = [NSTimer scheduledTimerWithTimeInterval:delay invocation:singleTapObjects repeats:NO];
This successfully calls the singleTapMethod and when looking at the debugger the objects passed are the same (location wise) but when calling [super touchesBegan:withEvent] on this method it does not handle it at all. Nothing happens. If I just implement the [super touchesBegan:withEvent] on the touchesBegan method it successfully handles it by forwarding it.

BTW already tried using self.nextResponder to try and force it myself to forward the touchesBegan but it won't work either.


Edit:

I did some more research and although the touch and event do get forwarded, when getting to the touchesBegan on the subview they have been forwarded to the reason they don't work is because getting the coordinates and/or the tapCount returns cero for the touch. Can anybody please shed some light on this situations?

Last edited by rnieves; 06-21-2009 at 02:22 AM.
rnieves is offline   Reply With Quote
Old 03-15-2010, 02:51 AM   #11 (permalink)
Registered Member
 
Join Date: Mar 2010
Posts: 4
Default

Quote:
Originally Posted by jeff_lamarche View Post
Setting a boolean is a bit kludgey, and will be hard to maintain for other tap situations (triple, quadruple, etc). There actually IS an "official" way to handle this situation described in the documentation. It's described, but Apple does not give sample code.

How you handle it is to call the correct method in each case using performSelector:withObject:afterDelay:, then, in each situation except single-tap, cancel the previous call before it executes (double-tap cancels the single-tap call, triple-tap cancels the double-tap call). This is what it might look like:


Code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
	UITouch *touch = [touches anyObject];
	NSUInteger tapCount = [touch tapCount];
	
	switch (tapCount) {
		case 1:
			[self performSelector:@selector(singleTapMethod) withObject:nil afterDelay:.4];
			break;
		case 2:
			[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTapMethod) object:nil];
			[self performSelector:@selector(doubleTapMethod) withObject:nil afterDelay:.4];
			break;
		case 3:
			[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(doubleTapMethod) object:nil];
			[self performSelector:@selector(tripleTapMethod) withObject:nil afterDelay:.4];
			break;
		case 4:
			[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(tripleTapMethod) object:nil];
			[self quadrupleTap];
			break;
		default:
			break;
	}

}
@end
Thanks for the answer, it helps me~~
Jackie is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


» Advertisements
» Stats
Members: 41,862
Threads: 49,770
Posts: 213,057
Top Poster: BrianSlick (3,139)
Welcome to our newest member, futurevilla216
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 07:05 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0