 |
 |
|
 |
09-09-2008, 02:37 PM
|
#1 (permalink)
|
|
New Member
Join Date: Aug 2008
Posts: 17
|
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.
|
|
|
09-09-2008, 10:43 PM
|
#2 (permalink)
|
|
Registered Member
Join Date: May 2008
Posts: 583
|
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.
|
|
|
09-10-2008, 12:44 AM
|
#3 (permalink)
|
|
New Member
Join Date: Aug 2008
Posts: 17
|
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.
|
|
|
09-10-2008, 07:16 AM
|
#4 (permalink)
|
|
New Member
Join Date: Apr 2008
Posts: 420
|
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
|
|
|
09-10-2008, 07:49 AM
|
#5 (permalink)
|
|
New Member
Join Date: Aug 2008
Posts: 17
|
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?
|
|
|
09-10-2008, 07:50 AM
|
#6 (permalink)
|
|
New Member
Join Date: Apr 2008
Posts: 420
|
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  ).
|
|
|
09-10-2008, 07:58 AM
|
#7 (permalink)
|
|
New Member
Join Date: Aug 2008
Posts: 17
|
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.
|
|
|
10-23-2008, 09:20 PM
|
#8 (permalink)
|
|
New Member
Join Date: Sep 2008
Posts: 2
|
Thank you. I can confirm that the multi-tapping works well
|
|
|
03-04-2009, 04:46 AM
|
#9 (permalink)
|
|
Registered Member
Join Date: Nov 2008
Posts: 19
|
Thanks
Thanks for providing the solution for this problem!!!!
|
|
|
06-21-2009, 01:13 AM
|
#10 (permalink)
|
|
Registered Member
Join Date: Feb 2009
Posts: 50
|
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.
|
|
|
03-15-2010, 02:51 AM
|
#11 (permalink)
|
|
Registered Member
Join Date: Mar 2010
Posts: 4
|
Quote:
Originally Posted by jeff_lamarche
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~~
|
|
|
 |
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
» Advertisements |
» Online Users: 426 |
| 40 members and 386 guests |
| AdamSubach, aderrington, anubhab123, benoitr007, BrianSlick, caseysackett, Danneman, dev123, ErichGS, futurevilla216, Gambit, GreatWizard, gustavo7sexton, gw1921, HemiMG, HowEver, iSDK, Jeremy1026, joelhull, lifeCoder45, mattiahalter, mcapraro, melodizzzy, mriphoneman, newchucky, Ovidius, Piequanna, qilin, Racker, rendezvouscp, riq, Sega dude, socals, themathminister, timle8n1, tinrocket, Whitehk, ZunePod |
| Most users ever online was 965, 06-30-2010 at 04:26 AM. |
» Stats |
Members: 41,862
Threads: 49,770
Posts: 213,057
Top Poster: BrianSlick (3,139)
|
| Welcome to our newest member, futurevilla216 |
|