Do not called UIGestureRecognizerStateEnded - iphone

I use on the my UIImageVIew the
-(IBAction)handlePanFrom:(UIPanGestureRecognizer *)recognizer
and in the my code I try to use a two state:
if([recognizer state] == UIGestureRecognizerStateBegan)
{
NSLog(#"Began");
}
if([recognizer state] == UIGestureRecognizerStateEnded)
{
NSLog(#"End");
}
in the console I see a "Began" message every time when I start move the UIImageView, but no any "End" message...
What I do wrong?

from apple doc:
UIGestureRecognizerStateEnded:
The gesture recognizer has received touches recognized as the end of a continuous gesture. It sends its action message (or messages) at the next cycle of the run loop and resets its state to UIGestureRecognizerStatePossible.
plz try UIGestureRecognizerStateCancelled

Related

UIGestureRecognizerStateBegan calling twice in iOS 6

Giving thanks in advance, I would like to share the strange behaviour of UILongPressGestureRecognizer.
UIView *v = [UIView alloc] initWithFrame:CGRectMake(0,0,20,20)];
UILongPressGestureRecognizer *longpressGesture1 = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[v addGestureRecognizer:longpressGesture1];
and here the delegate to handle the gesture recogniser.
-(IBAction)tapped:(UILongPressGestureRecognizer *) gesture
{
switch ([gesture state]) {
case UIGestureRecognizerStateBegan:
{
NSLog(#"Long Tap detacted.");
}
break;
case UIGestureRecognizerStateChanged:
{
NSLog(#"UIGestureRecognizerStateChanged");
}
break;
case UIGestureRecognizerStateEnded:
{
NSLog(#"Long Tap ended.");
}
break;
}
}
This piece of code is working perfectly as expected in iOS 4 and 5, but in ios 6 with retina display when we perform the long tap, UIGestureRecognizerStateBegan is being called twice for a single long tap resulting in a application crash.
Any help is greatly welcome.
UILongPressGestureRecognizer is a continuous event recognizer. You have to look at the state to see if this is the start, middle or end of the event and act accordingly.
Its calling two times because you are pressing and removing your finger.
First call is indicating you that there is an Long tap detected i.e. UIGestureRecognizerStateBegan
Second call is indicating you that there is end of that tap i.e. UIGestureRecognizerStateBegan
There are three state of tap
UIGestureRecognizerStateBegan
UIGestureRecognizerStateChanged
UIGestureRecognizerStateEnded
If you will drag your finger then it will called multiple time that will indicate that there is some changes in its state.
Follow UILongPressGestureRecognizer Class Reference for more

How to Implement Touch Up Inside in touchesBegan, touchesEnded

I'm wondering if someone knows how to implement the "touch up inside" response when a user pushes down then lifts their finger in the touchesBegan, touchesEnded methods. I know this can be done with UITapGestureRecognizer, but actually I'm trying to make it so that it only works on a quick tap (with UITapGestureRecognizer, if you hold your finger there for a long time, then lift, it still executes). Anyone know how to implement this?
Using the UILongPressGesturizer is actually a much better solution to mimic all of the functionality of a UIButton (touchUpInside, touchUpOutside, touchDown, etc.):
- (void) longPress:(UILongPressGestureRecognizer *)longPressGestureRecognizer
{
if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan || longPressGestureRecognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint touchedPoint = [longPressGestureRecognizer locationInView: self];
if (CGRectContainsPoint(self.bounds, touchedPoint))
{
[self addHighlights];
}
else
{
[self removeHighlights];
}
}
else if (longPressGestureRecognizer.state == UIGestureRecognizerStateEnded)
{
if (self.highlightView.superview)
{
[self removeHighlights];
}
CGPoint touchedPoint = [longPressGestureRecognizer locationInView: self];
if (CGRectContainsPoint(self.bounds, touchedPoint))
{
if ([self.delegate respondsToSelector:#selector(buttonViewDidTouchUpInside:)])
{
[self.delegate buttonViewDidTouchUpInside:self];
}
}
}
}
I'm not sure when it was added, but the property isTouchInside is a life saver for any UIControl derived object (e.g. UIButton).
override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
super.endTracking(touch, with: event)
if isTouchInside {
// Do the thing you want to do
}
}
Here's the Apple official docs
You can implement touchesBegan and touchesEnded by creating a UIView subclass and implementing it there.
However you can also use a UILongPressGestureRecognizer and achieve the same results.
I did this by putting a timer that gets triggered in touchesBegan. If this timer is still running when touchesEnded gets called, then execute whatever code you wanted to. This gives the effect of touchUpInside.
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSTimer *tapTimer = [[NSTimer scheduledTimerWithTimeInterval:.15 invocation:nil repeats:NO] retain];
self.tapTimer = tapTimer;
[tapTimer release];
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self.tapTimer isValid])
{
}
}
You can create some BOOL variable then in -touchesBegan check what view or whatever you need was touched and set this BOOL variable to YES. After that in -touchesEnded check if this variable is YES and your view or whatever you need was touched that will be your -touchUpInside. And of course set BOOL variable to NO after.
You can add a UTapGestureRecognizer and a UILongPressGestureRecognizer and add dependency using [tap requiresGestureRecognizerToFail:longPress]; (tap and long press being the objects of added recognizers).
This way, the tap will not be detected if long press is fired.

how to handle touch event like UITableView or ScollView

I made a customer control, inherit from UIView and add a lot of UIButtons on the UIView.
When a user touches and moves I will do some animation: let buttons move by the function touchesMoved:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
but buttonClick event seems to have a higher priority.
I want to it can like UITableView, scroll things have higher priority then button click.
You need to look into UIPanGestureRecognizer.
It allows you the ability to cancel events sent to other handlers.
Updated with additional information about how to safe previous points.
In the action callback, you gett notified of the initial touch location recognizer.state == UIGestureRecognizerStateBegan. You can save this point as an instance variable. You also get callbacks at various intervals recognizer.state == UIGestureRecognizerStateChanged. You can save this information also. Then when you get the callback with recognizer.state == UIGestureRecognizerStateEnded, you reset any instance variables.
- (void)handler:(UIPanGestureRecognizer *)recognizer
{
CGPoint location = [recognizer locationInView:self];
switch (recognizer.state)
{
case UIGestureRecognizerStateBegan:
self.initialLocation = location;
self.lastLocation = location;
break;
case UIGestureRecognizerStateChanged:
// Whatever work you need to do.
// location is the current point.
// self.lastLocation is the location from the previous call.
// self.initialLocation is the location when the touch began.
// NOTE: The last thing to do is set last location for the next time we're called.
self.lastLocation = location;
break;
}
}
Hope that helps.

(cocos2d sneaky input) when setting joystick position with touchLocation, sprite won't move

i want to let user choose where the joystick should be. i.e., when user touch at one location, the joystick will appear there and ready to use and will remove when finger released.
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if ([self getChildByTag:kTagJoyStick] == nil) {
[self addJoystickWithPosition:[Helper locationFromTouches:touches]];
}
}
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if ([self getChildByTag:kTagJoyStick] != nil) {
[self removeChildByTag:kTagJoyStick cleanup:YES];
}
}
-(void) ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self ccTouchesEnded:touches withEvent:event];
}
(do nothing in ccTouchesMoved method)
the update methods for joystick is:
-(void) sneakyUpdate {
if ([self getChildByTag:kTagJoyStick] != nil) {
if (joystick.velocity.x < 0) {
[self controlLeft];
}
else if (joystick.velocity.x > 0) {
[self controlRight];
}
else {
[self controlStop];
}
}
else {
[self controlStop];
}
}
but the result is, the joystick will appear and auto remove. but my sprite won't move. ( i set the break point, the sneakyUpdate method did get called. but the joystick.velocity is always 0. (and the thumbSprite didn't follow our finger.
please help me.
update:
and it turns out that i have to use 2 fingers (one for touch once and let the joystick show up, move my finger away, and then use another finger to control the joystick)
I'm not 100% sure, but I think you should use ccTouchBegan instead ccTouchesBegan, because sneakyJoystick classes use ccTouchBegan/Moved/Ended/Cancelled. Also, there are for a single touch, that is what you want.
I hope it works!
It looks like the problem is in your joystick class. Every joystick implementation I've seen uses the ccTouchesBegan method to activate the joystick, then in the ccTouchesMoved method, it makes sure its activated before using it. The problem I am seeing is that you create and add the joystick AFTER the touches began method, meaning your joystick never 'activates'. One way of bypassing this is to do all of the joystick's ccTouchesBegan functions in the method that creates the joystick, and 'activate' it from there by passing a reference to the touch that will be using it.

How to create touch events for MKMapView?

How to create Touch Events for MKMapView.
I'm using UIViewController and adding MKMapView on that using interface builder.
Now I need to handle touch events for that map.....
I tried by writing UITouch Delegate methods
But I failed...It is not getting called.
Please post a solution how to handle touch events on MKMapView.....
Thanks in advance...
If you are happy with an iOS 4 and above solution, I've used UIGesture recognisers and never had a problem.
Here's an example for a long pressure gesture (tap and hold):
// Long press gesture recogniser
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleLongPressGesture:)];
[self.view addGestureRecognizer:longPressGesture];
[longPressGesture release];
And then you can handle the even in your handleLongPressGesture: method:
-(void)handleLongPressGesture:(UILongPressGestureRecognizer*)sender
{
if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateChanged)
return;
else {
// Your app logic here...
}
}