In my mapview I am using the long press gesture to draw an MKCircle on the map. I'd like to use a double tap gesture to remove the circle. I add double tap as a gesture recognizer and it works correctly, however, while it removes the circle it also zooms a bit each time. I am wondering if there is a way to remove the default zoom by double tap behavior leaving just my own? I don't want to disable zooming for the whole map just when doing a double tap.
UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(getMapCoordinateFromTouch:)];
[self.mapView addGestureRecognizer:longGesture ];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(removeBoundary:)];
[tapGesture setNumberOfTapsRequired:2];
[tapGesture setNumberOfTouchesRequired:1];
tapGesture.delegate = self;
[self.mapView addGestureRecognizer:tapGesture];
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
-(void)removeBoundary:(UITapGestureRecognizer *)gesture
{
[self.mapView removeOverlays:self.mapView.overlays];
}
Additional Info:
It was suggested that this question was similar to: Disable double tap zoom in MKMapView (iOS 6)
However, that person was trying to disable all double taps and not just the default behavior. I did find some code in that question that I thought may help here but it does not. In that thread it was indicated that you could loop through the mapview and remove the gesture recognizer. This seems to work for gesture recognizers that I may add but it does not find any of the Apple default behaviors. I run the following code after viewWillAppear (I also tried viewDidAppear) but a break point shows that "gestures" is nil. So for some reason the view does not have Apple's default gestures.
NSArray *gestures = [self.mapView gestureRecognizers];
for (UIGestureRecognizer *recognizer in gestures)
{
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]])
{
UITapGestureRecognizer *tap = (UITapGestureRecognizer *)recognizer;
if (tap.numberOfTapsRequired == 2)
[self.mapView removeGestureRecognizer:recognizer];
}
}
Default UIGestureRecognizers appear to be added to the first subview, just remove them:
Example to remove all UITapGestureRecognizers (go from 13 to 9)
Swift:
print("GestureRecognizers before \(mainMap.subviews[0].gestureRecognizers?.count)")
if (mainMap.subviews[0].gestureRecognizers != nil){
for gesture in mainMap.subviews[0].gestureRecognizers!{
if (gesture.isKindOfClass(UITapGestureRecognizer)){
mainMap.subviews[0].removeGestureRecognizer(gesture)
}
}
}
print("GestureRecognizers after \(mainMap.subviews[0].gestureRecognizers?.count)")
Objective-C:
NSArray *gestures = [self.mapView.subviews.firstObject gestureRecognizers];
for (UIGestureRecognizer *recognizer in gestures)
{
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]])
{
UITapGestureRecognizer *tap = (UITapGestureRecognizer *)recognizer;
if (tap.numberOfTapsRequired == 2)
[self.mapView.subviews.firstObject removeGestureRecognizer:recognizer];
}
}
Try returning NO from -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:. It sounds like both your recognizer and the map view's recognizer are acting on the double tap. You really want yours to get first crack at the gesture, so it can effectively override the map view's.
Related
I'd like to enable UIPanGestureRecognizer on customView when the customView did longPress.
(I wish when you longPress customView, the customView will switch to "move mode", and you can move the customView by drag.)
But in this code, only longPressAction: called. panAction: did not called.
How do I fix it to enable PanAction:?
- (void)viewDidLoad
{
[self.view addSubview:customView];
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(longPressAction:)];
[customView addGestureRecognizer:longPressRecognizer];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(panAction:)];
[customView addGestureRecognizer:panRecognizer];
}
- (void)longPressAction:(UILongPressGestureRecognizer *)recognizer
{
if ([recognizer state] == UIGestureRecognizerStateBegan) {
CustomView *customView = (CustomView *)recognizer.view;
customView.panRecongnizerEnabled = YES; //panRecongnizerEnabled is CustomView's property
}
if ([recognizer state] == UIGestureRecognizerStateEnded) {
CustomView *customView = (CustomView *)recognizer.view;
customView.panRecongnizerEnabled = NO;
}
}
- (void)panAction:(UIPanGestureRecognizer *)recognizer
{
CustomView *customView = (CustomView *)recognizer.view;
if (customCell.panRecongnizerEnabled == NO) return;
NSLog(#"running panAction");
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Your ViewController needs to conform to the UIGestureRecognizerDelegate. I suspect you either already did that or otherwise the shouldRecognizeSimultaneouslyWithGestureRecognizer would not make any sense. But what you are definitely missing is setting the gestureRecognizer´s delegate to your viewController:
longPressRecognizer.delegate = self;
panRecognizer.delegate = self;
Now you should be receiving both long press and pan simultaneous.
Note: I tested without any customView, just added them to self.view. At least in that case, the code above worked as expected.
I know this question has been closed for a while, but I recently had to do something similar, and there is a much cleaner solution. The UILongPressGestureRecognizer is all you need to do this.
Long-press gestures are continuous. The gesture begins
(UIGestureRecognizerStateBegan) when the number of allowable fingers
(numberOfTouchesRequired) have been pressed for the specified period
(minimumPressDuration) and the touches do not move beyond the
allowable range of movement (allowableMovement). The gesture
recognizer transitions to the Change state whenever a finger moves,
and it ends (UIGestureRecognizerStateEnded) when any of the fingers
are lifted.
Because of this, for what you need, there is no need for the UIPanGestureRecognizer. Simply add the UILongPressGestureRecognizer and attach it to your main view.
- (void)viewDidLoad {
[super viewDidLoad];
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(longPressAction:)];
// set this to your desired delay before the pan action will start.
longPressRecognizer.minimumPressDuration = 0.5;
[self.view addGestureRecognizer:longPressRecognizer];
}
Then, implement the longPressAction method to look at not just UIGestureRecognizerStateBegan or UIGestureRecognizerStateEnded states, but also the UIGestureRecognizerStateChanged state:
- (void)longPressAction:(UIGestureRecognizer *)recognizer
{
if ([recognizer state] == UIGestureRecognizerStateBegan || [recognizer state] == UIGestureRecognizerStateChanged ) {
CGPoint touchPoint = [recognizer locationInView:self.view];
[self.viewToMove setCenter: touchPoint];
NSLog(#"running panAction");
}
}
In my example, I simply move a dummy view to track the center of the user's finger, but you can put any logic you would have put in the UIPanGestureRecognizer's code. Simply put it inside the if block and it greatly simplifies your code and you don't need to deal with interactions between the two gesture recognizers. Your code would also result in many needless calls to the panAction method when the user is simply moving their finger around the screen (but hasn't done a long press).
You can do it by enabling the pan after the long press. Anyhow you will have to save a flag to know if the longPress was called. And in order to enable the pan gesture after the longPress, you can play with the pan gesture delegate, as following:
let previewLongPress = UILongPressGestureRecognizer(target: self, action: #selector(onLongPressed(sender:)))
let previewPanGesture = UIPanGestureRecognizer(target: self, action: #selector(onPanGesture(sender:)))
previewPanGesture?.delegate = self
Your delegate should seems like this:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return gestureRecognizer == previewPanGesture && otherGestureRecognizer == previewLongPress
}
And now you're able to have a pan gesture after a long press gesture.
Hope it helps other people.
Ok so I am helping convert an android game to iOS. The game is based on 2048, but with letters instead of numbers. I have a good bit of it working but am still learning Objective C/iOS quirks. So far I have the tiles/grid working, movement is working, etc but I need a bit of help. The goal is to allow the user to long-press on a tile to select it, then slide their finger to an adjacent tile to begin spelling a word. I have the long press portion implemented but I'm at a bit of a loss on how to get it to long-press then swipe. On top of this I already have a swipe that allows the user to move the tiles. In searching on here I've seen suggestions about subclassing so I am figuring I need to subclass the UISwipeGestureRecognizer method. I already put in the simultaneously gesture recognizer, but am unsure where to go from here.
So, there are several questions to this.
What would be the best way to do this? Implement a subclass of each UISwipeGestureRecognizer?
Will my current swipe detection interfere? (right now a swipe by itself moves tiles in direction of swipe)
I would guess I need to do a (if long press) then activate subclassed swipe methods?
Any examples to answer the above questions would be of great help. I'm not asking you to do it for me but at least point me in a general direction. Thanks!
Code below.
// Grid.m
#import "Grid.h"
#import "Tile.h"
- (void)didLoadFromCCB {
// listen for swipes to the left
UISwipeGestureRecognizer * swipeLeft= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeLeft)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[[[CCDirector sharedDirector] view] addGestureRecognizer:swipeLeft];
// listen for swipes to the right
UISwipeGestureRecognizer * swipeRight= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeRight)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[[[CCDirector sharedDirector] view] addGestureRecognizer:swipeRight];
// listen for swipes up
UISwipeGestureRecognizer * swipeUp= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeUp)];
swipeUp.direction = UISwipeGestureRecognizerDirectionUp;
[[[CCDirector sharedDirector] view] addGestureRecognizer:swipeUp];
// listen for swipes down
UISwipeGestureRecognizer * swipeDown= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeDown)];
swipeDown.direction = UISwipeGestureRecognizerDirectionDown;
[[[CCDirector sharedDirector] view] addGestureRecognizer:swipeDown];
// listen for long press
UILongPressGestureRecognizer *longpress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(onLongPress:)];
[longpress setMinimumPressDuration:0.5];
[[[CCDirector sharedDirector] view] addGestureRecognizer:longpress];
}
- (void)swipeLeft {
[self move:ccp(-1, 0)];
}
- (void)swipeRight {
[self move:ccp(1, 0)];
}
- (void)swipeDown {
[self move:ccp(0, -1)];
}
- (void)swipeUp {
[self move:ccp(0, 1)];
}
// detect longpress, convert to NodeSpace and check if touch location is within tile boundingbox. If yes, set background white, text black.
- (void)onLongPress:(UILongPressGestureRecognizer *) recognizer {
CGPoint touchPoint = [[CCDirector sharedDirector] convertToGL:[recognizer locationInView:[recognizer view]]];
touchPoint = [self convertToNodeSpace:touchPoint];
if (recognizer.state == UIGestureRecognizerStateBegan) {
for (Tile *tile in self.children) {
if([tile isKindOfClass:[Tile class]]) {
CGRect tileBoundingBox = tile.boundingBox;
if (CGRectContainsPoint(tileBoundingBox, touchPoint)) {
tile.backgroundNode.color = [CCColor whiteColor];
tile.valueLabel.color = [CCColor blackColor];
[self spellWord:tile.value];
[_word setString:[_word lowercaseString]];
CCLOG(#"%#", _word);
}
}
}
}
if (recognizer.state == UIGestureRecognizerStateChanged) {
}
if (recognizer.state == UIGestureRecognizerStateEnded) {
for (Tile *tile in self.children) {
if([tile isKindOfClass:[Tile class]]) {
CGRect tileBoundingBox = tile.boundingBox;
if (CGRectContainsPoint(tileBoundingBox, touchPoint)) {
tile.backgroundNode.color = [tile getColor:tile.value];
tile.valueLabel.color = [self getContrastColor:r green:g blue:b];
}
}
}
}
}
// allow for simultaneous gestures
- (BOOL)gestureRecognizer:(UIGestureRecognizer *) recognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
In answer to your questions:
This doesn't strike me as a coding situation that requires one to subclass UILongPressGestureRecognizer. Having said that, subclassing is often a nice way to clean up one's view controller code so you don't have gory gesture recognizer code in the view controller class. But there's nothing here (as I understand it) that demands that. You generally dive into subclassing of gesture recognizers where you need some special custom behavior (e.g. have the gesture fail if some complicated criterion fails). I'd first see if you could achieve the desired UX with standard gestures before I went down that road, though.
The only reason I could see the swipe gestures interfering with each other is that you've specified that shouldRecognizeSimultaneouslyWithGestureRecognizer should return YES. That's used in cases where you need multiple recognizers running at the same, which doesn't seem necessary here (and only a source of problems).
It's unclear to me as to whether you really wanted a separate swipe gesture or whether you just wanted a single gesture ("long press and drag"). If you needed that separate swipe gesture, though, you would generally specify the relative priority of gesture recognizers by specifying requireGestureRecognizerToFail (e.g. have the swipe require long press to fail in order for the swipe to be recognized). But if you really only have one gesture ("long press and drag"), then only one gesture recognizer is needed.
It seems unnecessary. If you want to detect movement after the long press has been recognized, you can put that "move after long press" code in the if statement for UIGestureRecognizedStateChanged in your onLongPress, which occurs after the long press has been recognized, but before the user lifts their finger. The UILongPressGestureRecognizer is a continuous gesture recognizer which will continue to get updates as the user's finger moves after the gesture was initially recognized.
I know you didn't ask for code, but if you wanted a swipe gesture, as well as a long press gesture that was, essentially, the idea of picking it up and dragging it, you could do something like the following. Note, I make the swipe gesture require the long press to fail, so if the user is long pressing, that takes precedence, otherwise it does swipe. But you may not need the swipe gesture at all, so if you don't need it, just remove it altogether:
#import <UIKit/UIGestureRecognizerSubclass.h>
- (void)viewDidLoad {
[super viewDidLoad];
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
[self.view addGestureRecognizer:longPress];
// if you needed a second gesture, a swipe, completely distinct from the long press and drag
// gesture, you could add it like so:
//
// UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipe:)];
// [swipe requireGestureRecognizerToFail:longPress];
// // do additional swipe configuration
// [self.view addGestureRecognizer:swipe];
}
- (void)handleSwipe:(UISwipeGestureRecognizer *)gesture
{
// do your separate swipe stuff here
}
- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
{
static UIView *tileToMove;
static CGPoint startCenter;
static CGPoint startLocation;
CGPoint location = [gesture locationInView:self.view];
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
{
// find the tile
tileToMove = [self findTileToMove:location];
if (tileToMove) {
// if found, capture state ...
startCenter = tileToMove.center;
startLocation = location;
// ... and animate "pick up tile", so the user gets positive feedback
// that the drag/swipe portion of the gesture is starting.
[UIView animateWithDuration:0.25 animations:^{
tileToMove.transform = CGAffineTransformMakeScale(1.2, 1.2);
}];
} else {
gesture.state = UIGestureRecognizerStateFailed;
}
break;
}
case UIGestureRecognizerStateChanged:
{
// move the tile as the user's finger moves
CGPoint translate = CGPointMake(location.x - startLocation.x, location.y - startLocation.y);
// note, if you want to constrain the translation to be, for example, on the
// x-axis alone, you could do something like:
//
// CGPoint translate = CGPointMake(location.x - startLocation.x, 0);
tileToMove.center = CGPointMake(startCenter.x + translate.x, startCenter.y + translate.y);
break;
}
case UIGestureRecognizerStateEnded:
{
// animate "drop the tile"
[UIView animateWithDuration:0.25 animations:^{
tileToMove.transform = CGAffineTransformIdentity;
// if you want the tile to "snap" to some location having let it go,
// set the `center` or `frame` here.
}];
// clear our variables, just in case
tileToMove = nil;
startCenter = CGPointZero;
startLocation = CGPointZero;
break;
}
default:
break;
}
}
- (UIView *)findTileToMove:(CGPoint)location
{
for (UIView *tile in self.tiles) {
if (CGRectContainsPoint(tile.frame, location)) {
return tile;
}
}
return nil;
}
This might not be quite the exact UI you're looking for, but it illustrates:
How to have two gestures, where one requires the other to fail in order to establish a precedence between the gestures (and clearly only an issue if you want two distinct gestures, which you probably don't);
To not have shouldRecognizeSimultaneouslyWithGestureRecognizer method because I don't want them both to be recognized simultaneously. Note, that's only needed if you really need two gestures, which you may or may not need; and
How to have a long press that not only recognizes initial long press, but subsequent swipe/drag movement, too.
I have a small problem that em stuck on.. i have a Custom UITableViewCell, on its textView i have added 2 gestures, UITapGesture and UISwipeGesture.. the tap gesture is working fine but the swipe gesture is calling the method multiple times.. some times calling it twice and some times even more than that… Here's how i have added them to the cell
//added in cellForRowAtIndexPath Method
UITapGestureRecognizer *tapToTranslate = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapToTranslate:)];
[tapToTranslate setNumberOfTapsRequired:1];
[tapToTranslate setNumberOfTouchesRequired:1];
tapToTranslate.delegate = self;
[cell.messageContentView addGestureRecognizer:tapToTranslate];
UISwipeGestureRecognizer *swipeToTranslate = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(translateTo:)];
swipeToTranslate.numberOfTouchesRequired = 1;
swipeToTranslate.direction = UISwipeGestureRecognizerDirectionLeft;
swipeToTranslate.delegate = self;
[cell.messageContentView addGestureRecognizer: swipeToTranslate];
These are there methods…
-(void)tapToTranslate:(UITapGestureRecognizer *)aGesture {}
-(void)translateTo:(UISwipeGestureRecognizer *)aGesture
{
aGesture.enabled = false;
}
I've tried to disable Swipe Gesture in its method after its called but that didn't help..
I've also have the uigesturerecognizer delegate method
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
So Any help would be great…
thanks in advance…
EDIT 1
<UITextView: 0x11322f700; frame = (18 10; 160.865 69.2656); text = '你怎么样? How are you doing?'; clipsToBounds = YES; gestureRecognizers = <NSArray: 0x11322fbd0>; layer = <CALayer: 0x11322fac0>; contentOffset: {0, 0}>
The UISwipeGestureRecognizer does call the function multiple times for different states like UIGestureRecognizerStateBegan, UIGestureRecognizerStateEnded, and several other states. It also keeps on calling the function constantly while it is swiping which can be handled in the last else statement below. In the swipe gesture function, do this:
-(void)translateTo:(UISwipeGestureRecognizer *)aGesture
{
if (recognizer.state == UIGestureRecognizerStateBegan)
{
//do something
}
else if(recognizer.state==UIGestureRecognizerStateEnded)
{
}
else
{
//do something while it is swiping
}
}
The below answer may not be in correspondence to what you intend to do but still might help you: UISwipeGestureRecognizer called twice
After Removing the gesture.delegate = self; line from both the gestures, the method started calling once as it was suppose to do. Apparently doing the job for me. So for anyone facing this issue, they can try removing the gesture's delegate and its method.
The thing is, Tableview is having its own gesture recognizers. By adding additional gestures over the tableview it is somehow confusing with the gesture to call. This might be the reason of this issue. Here is the solution;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([gestureRecognizer.view isKindOfClass:[UITableView class]]) {
...
} else {
...
}
}
You can recognize simultaneous gestures using this.
I have a UIView with two gesture recognizers. Both recognize tap with two fingers: one for the upper half of the screen, the other for the bottom of the screen.
In that UIView, I have 4 buttons that cover the entire screen (each button is a quarter of the screen).
I'm using the gesture recognizer to detect when the user presses 2 buttons at the same time, and I still want to recognize the normal touches on the buttons.
I've setup everything, and it works fine. However, when pressing with just one finger the shadow on the button appears on Touch Up, and not on Touch Down. And it feels weird. I've tried to change delaysTouchesBegan with no success.
Is there a way to have both behaviours? Detect the touches with two fingers, but have a "normal behaviour" when there's only one finger? Otherwise, can I force the pressed state of a UIbutton?
Here's how I setup my gestures :
-(void)initGestureRecognition{
handClapTapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handClapDetected:)];
handClapTapGestureRecognizer.numberOfTouchesRequired = 2;
handClapTapGestureRecognizer.numberOfTapsRequired = 1;
handClapTapGestureRecognizer.cancelsTouchesInView = YES;
[self.gestureRecognitionView addGestureRecognizer:handClapTapGestureRecognizer];
handClapTapGestureRecognizer.delegate = self;
jumpTapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(jumpDetected:)];
jumpTapGestureRecognizer.numberOfTouchesRequired = 2;
jumpTapGestureRecognizer.numberOfTapsRequired = 1;
jumpTapGestureRecognizer.cancelsTouchesInView = YES;
[self.gestureRecognitionView addGestureRecognizer:jumpTapGestureRecognizer];
jumpTapGestureRecognizer.delegate = self;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return NO;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if ([gestureRecognizer isEqual:handClapTapGestureRecognizer] && [touch locationInView:self.view].y > self.view.frame.size.height/2)
return NO;
if ([gestureRecognizer isEqual:jumpTapGestureRecognizer] && [touch locationInView:self.view].y < self.view.frame.size.height/2)
return NO;
return YES;
}
I know my problem is similar to that one : UIButton inside a view that has a UITapGestureRecognizer but the difference is that in my case, the behaviour is ok, and I'm just trying to get the shadow on the button on Touch DOwn, rather than on Touch Up.
Thanks
Could you manually set [button setHighlighted:YES] when the tap gesture is first recognized and its location matches that of the button's, and then to NO when the gesture ends?
I've been trying to use a UILongPressGestureRecognizer in a MKAnnotationView subclass. Interestingly the gesture recognizer only triggers when using two ore fingers/touches.
What prevents the gesture recognizer to get triggered with only one touch?
Implementation
UILongPressGestureRecognizer *pressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
action:#selector(handleLongPress:)];
pressRecognizer.minimumPressDuration = 0.25;
pressRecognizer.numberOfTapsRequired = 0;
pressRecognizer.numberOfTouchesRequired = 1;
The same implementation in a normal UIView shows the expected behaviour working with one touch. Yet it's possible to use touchesBegan: and touchesEnded: to get a long press gesture working I'm still curious what the reason for this is.
Have you seen this question ?
For using my UILongPressGestureRecognizer I disabled AnnotationView and added GestureRecognizer to it:
[ann_view setEnabled:NO];
UILongPressGestureRecognizer* long_press = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressAnnotationView:)];
long_press.minimumPressDuration = 1.5;
[ann_view addGestureRecognizer:long_press];
[long_press release];