I'm trying to implement ccTouchesBegan in my GameScene.
I've set isTouchEnabled = YES. I'm also calling addStandardDelegate on the touchDispatcher. Finally, in my AppDelegate i have [glView setMultipleTouchEnabled:YES].
However, ccTouchesBegan is never called.
What am I doing wrong?
Solved it!
I was registering touches on a previous layer, but the layer wasn't being dealloced because you have to "un-register" with the onExit method.
Long story short: touchesBegan was not being called on my GameLayer because it was being swallowed by another layer.
Create one dummy application and try this:
#protocol CCStandardTouchDelegate <NSObject>
#optional
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
#end
May be it will help you..
Related
I'm building a game that basically the goal is to hold a button pressed for a long time.
The game starts with the "touchesBegan" call, and ends on "touchesEnded".
I have a issue that some very specific times this call, is not called. After a some search i figured out i'm not the only one with this problem :
https://discussions.apple.com/thread/1507669?tstart=0
There is a known problem that some times "touchesEnded" is not called.
So the work around i was thinking of doing, is setting a timer, and checking every once in a while, if there is a finger pressing, and where exactly on the screen.
Problem is, i know only about these methods:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
And nun of them serve me for this use.
Is there a way of getting the current touch on screen?
Thanks
touchesCancelled:withEvent:
When a touch begins, touchesBegan:withEvent: is called. After that, at some point in the future, either touchesEnded:withEvent: or touchesCancelled:withEvent: will be called! You can, e.g. create a method touchesEndedOrCancelled:withEvent: and call that method from both touchesEnded and touchesCancelled.
To get the current touches you need to keep track of them on your own. Just create a mutable set _allTouches
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[_allTouches unionSet:touches];
// ...
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[_allTouches minusSet:touches];
// ...
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[_allTouches minusSet:touches];
// ...
}
I searched but not quite understand why we cant detect a UITouch on UITableView. What I am having right now is :a view controller with a table view located in its view. Please look at the picture below for your reference
In implementation class, I am enabling breakpoint for each UITouch methods which are
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
I notice that, these breakpoints are invoked if and only if you touch outside of the table view ( orange area )
I do not get it. I thought UITableView is subclass of UIScrollView which is subclass of UIView which is subclass of UIResponder. It means UITouch should be invoked. (correct me if I am wrong )
All comments are welcomed and appreciated here.
Rather than tampering with the table view, use a gesture recognizer. You can act as the delegate to ensure that all interactions work concurrently and enable and disable the gestures if / as required.
You can detect touches method in the UITableView by subclassing it as this:
I Test it and it print "Test" successfully
//TestTable.h
#import <UIKit/UIKit.h>
#interface TestTable : UITableView
#end
//TestTable.m
#import "TestTable.h"
#implementation TestTable
(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog("Test");
}
Tables utilize scroll views to handle panning, which use a pan gesture recognizer. Why not just tap into that?
CGPoint location = [self.tableView.panGestureRecognizer locationInView:self.tableView];
If you wish to detect the touches on UITableView, create a subclass of tableview and add implement UIResponder method, canBecomeFirstResponder.
#interface MyTableView: UITableView
#end
#implementation: MyTableView
- (BOOL) canBecomeFirstResponder{
return YES;
}
// then implement all other touch related methods, remember to call super in these methods
// such that it correctly forwards the events to other responders
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
}
#end
I'm trying to enable touch for layers as many other people have suggested online:
hudLayer = [[[CCLayer alloc] init] autorelease];
[self addChild:hudLayer z:3];
gameLayer = [[[CCLayer alloc] init] autorelease];
[self addChild:gameLayer z:1];
gameLayer.isTouchEnabled = YES;
rileyLayer = [[[CCLayer alloc] init]autorelease];
[self addChild:rileyLayer z:2];
pauseMenu = [[[CCLayer alloc] init] autorelease];
[self addChild:pauseMenu z:4];
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:hudLayer priority:0 swallowsTouches:YES];
and my touchmethods are here:
- (BOOL)ccTouchBegan:(NSSet *)touch withEvent:(UIEvent *)event {
return TRUE;
}
- (void)ccTouchEnded:(NSSet *)touch withEvent:(UIEvent *)event {
if (!paused) {
ratMove = 0;
}
}
however this continually throws the error: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Layer#ccTouchBegan override me'
The only reason I could find for this error online is if you weren't including the ccTouchBegan function, however I am, does anyone else know any other reasons for this error to appear?
Subclass CCLayer to have hud layer, then inside it implement these methods.
You add your hud layer as targeted delegate, then it must implement at least ccTouchBegan:withEvent: method. If you want your hud to be targeted delegate, make CCLayer subclass and implement there methods from targeted touch delegate protocol.
your function does not implement the appropriate signature. Try:
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
// your stuff here
}
if you want multiple touch handling (your signature), you should addStandardDelegate instead of targetedTouchDelegate.
EDIT : and now in objective-c:
[[CCDirector sharedDirector].touchDispatcher addStandardDelegate:self priority:0];
There are two protocols implemented by the touch dispatcher. You are currently registering as a targetTouchDelegate but implementing the delegate methods of the standardDelegate. Use the line above to register if you want to keep your methods.
Edit 2 : and now the exact syntax of the protocols, straight from cocos's code. As you can see, no ccTouchBegan with NSSet (your signature) BUT INSTEAD ccTouchesBegan. Whichever handling method you prefer (targeted of standard), you must conform to the protocols below.
#protocol CCTargetedTouchDelegate
/** Return YES to claim the touch.
#since v0.8
*/
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event;
#optional
// touch updates:
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event;
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event;
- (void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event;
#end
/**
CCStandardTouchDelegate.
This type of delegate is the same one used by CocoaTouch. You will receive all the events (Began,Moved,Ended,Cancelled).
#since v0.8
*/
#protocol CCStandardTouchDelegate <NSObject>
#optional
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
#end
I subclassed the UIWindow, but for some reason the - (void)sendEvent:(UIEvent *)event gets called 2 times for any interaction with the screen. Any ideas why would that happen?
For debugging purposes, subclass window (of app delegate) and override sendEvent: method
-(void) sendEvent:(UIEvent *)event
{
NSLog(#"%#",event);
[super sendEvent:event];
}
Most probably, you will notice the events responsible for TouchesBegan and TouchesEnded (for tapping). This can be tested by subclassing the View and overriding touch related methods.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"tocuhesBegan");
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesMoved");
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesEnded");
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesCancelled");
}
Also, try drag/swipe on the view to notice the change in count of events sent to view :)
sendEvent gets called for fingerDown and allFingersUp
I am dtecting touches on my UIView.
Is some situations I want to be abel to cancel touches so that touchesEnded won't get called. But doesn't matter what touchesEnded will always get called?
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (SOMETHING_SPECIAL)
{
[super touchesCancelled:touches withEvent:event];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//I don't want it to get here if touches were canceled how can i do this?
}
- In my touchesEnded how can I determine whether touches were canceled or not?
TouchesEnded will always get called wherever your touches where canceled or not, so I would suggest instead having that exact:
if (SOMETHING_SPECIAL)
{
}
In your:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
To get the touchesCancelled event, implement this method from UIResponder.
touchesCancelled:withEvent:.