I'm setting up a LPGR like so and I was wonder if I can create a tag in each LPGR. I need to do this so I know which of all my buttons is being pressed...
UILongPressGestureRecognizer *longpressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressHandler:)];
longpressGesture.minimumPressDuration = 2;
[longpressGesture setDelegate:self];
[pushButton addGestureRecognizer:longpressGesture];
And my method below...
- (void)longPressHandler:(UILongPressGestureRecognizer *)gestureRecognizer {
NSLog(#"longPressHandler");
}
I know you can't pass arguments via selectors, so I was wondering if I could assign a tag to the LPGR or if in the method I could grab the tag of the button that was using the LPGR? Is any of this possible>?
EDIT:
NSInteger *tag = [gestureRecognizer.view.tag];
NSLog(#"%# longPressHandler",tag);
UIGestureRecognizer has a property view which is the view the gesture recognizer is attached to.
Therefore, in your handler method, gestureRecognizer.view is the button that the LPGR is attached to and gestureRecognizer.view.tag is the button's tag.
ADDED:
Sample code:
- (void)longPressHandler:(UILongPressGestureRecognizer *)gestureRecognizer {
NSLog(#"longPressHandler");
NSInteger tag = gestureRecognizer.view.tag;
NSLog(#"%d longPressHandler",tag);
}
You can simply create a subclass of UILongPressGestureRecognizer and add a tag property to it. You could also use associated objects to add the property with a category.
Related
I want use tap gesture and long press gesture together in a view. But my problem is that I can't able to run tap gesture action on tap. But Long press gesture is working fine.
Here is code snippet.
UILongPressGestureRecognizer *longPressGesture=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(ontappLongPressGesture:)];
longPressGesture.minimumPressDuration=0.6;
longPressGesture.delegate=self;
[cell.view addGestureRecognizer:longPressGesture];
UITapGestureRecognizer *gesture=[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(cellSelected:)];
//[gesture requireGestureRecognizerToFail:longPressGesture]; //I have tried with this line also but not working
gesture.delegate=self;
[cell.view addGestureRecognizer:gesture];
Also I have set delegate method also
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
This method is getting called on long press
- (void)ontappLongPressGesture:(id)sender{
//Long press code here
}
But this method is not getting called on tap
-(void)cellSelected:(id)sender {
//Single tap code here
}
You haven't specified what type of view your putting these gestureRecognizer's on, however since you are calling it "cell", I'm assuming its on a UITableView?
You need to make sure you set the cancelsTouchesInView flag if so:
gesture.cancelsTouchesInView=NO;
You either need to use one of these two ways.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// test if our control subview is on-screen
if (cell.view.superview != nil) {
if ([touch.view isDescendantOfView:cell.view]) {
// we touched our control surface
return YES; // handle the touch
}
}
return NO; // ignore the touch
}
Here you need to specify the view for which you want the gestureRecognizer.
Or you can also use these lines of code
gesture.cancelsTouchesInView = NO;
longPressGesture.cancelsTouchesInView = NO;
Hope it will help you.
I have a table view, and I use UILongPressGestureRecognizer on table view cell to show a context menu over the cell to allow user perform some extra functionality. Everything is work well in iOS 5.1, but when I test in iOS 5 and 4.3, the event is not fired.
Does anyone know how to solve this problem please help me, thanks in advance.
Below is my code:
in tableViewCell.h: add UIGestureRecognizerDelegate
in tableViewCell.m
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
longPressRecognizer.minimumPressDuration = 1.5;
longPressRecognizer.numberOfTouchesRequired = 1;
longPressRecognizer.numberOfTapsRequired = 0;
longPressRecognizer.delegate = self;
[self addGestureRecognizer:longPressRecognizer];
[longPressRecognizer release];
// Method to handle event
- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
{
// Do something.
}
}
After spending 1.5 days on this issue, I discover that somehow the tableView receives long press event but tableViewCell does not on iOS 5/4.3 . So I fixed this issue by adding UILongPressGuestureRecognizer to tableView then in the long press event handler then call tableViewCell to show the context menu, and it works.
I met this problem too. I found that long press gesture recognizer works fine only when 'delegate' property is 'NULL'. So just try to remove this line.
longPressRecognizer.delegate = self;
guys,
I have added two UILongPressGestureRecognizer. What I want is when two buttons are pressed down for 0.3 second, fire up "shortPressHandler". If user keeps pressing these two buttons for another 1.2 second, fire up "longPressHandler". Now I only get shortPressHandler fired up and the longPressHandler was never fired. I think it might because the shortPressGesture is recognized first and longPressGesture never gets a chance. Can anyone show me how to achieve what I want? Thanks in advance.
UILongPressGestureRecognizer *longPressGesture =[[[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressHandler:)] autorelease];
longPressGesture.numberOfTouchesRequired = 2;
longPressGesture.minimumPressDuration = 1.5;
longPressGesture.allowableMovement = 10;
longPressGesture.cancelsTouchesInView = NO;
longPressGesture.enabled = true;
[self.view addGestureRecognizer:longPressGesture];
UILongPressGestureRecognizer *shortPressGesture =[[[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(shortPressHandler:)] autorelease];
shortPressGesture.numberOfTouchesRequired = 2;
shortPressGesture.minimumPressDuration = 0.3;
shortPressGesture.allowableMovement = 10;
shortPressGesture.cancelsTouchesInView = NO;
shortPressGesture.enabled = true;
[self.view addGestureRecognizer:shortPressGesture];
Insert this line before adding shortPressGesture:
[shortPressGesture requireGestureRecognizerToFail:longPressGesture];
Note: shortGesture will not get called immediately after 0.3 seconds of holding but when the tap is released if it was between 0.3 seconds and 1.2 seconds long. If the tap is longer than 1.2 s (you have 1.5s in your code which is probably a typo) only longPressGesture will fire up.
EDIT:
However, if you want your event handlers both to fire (in an event of long press), you should do this:
Your UIView of should implement the <UIGestureRecognizerDelegate> in .h file.
In .m file you add this method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Now instead of adding the line:
[shortPressGesture requireGestureRecognizerToFail:longPressGesture];
You add this two lines:
shortPressGesture.delegate = self;
longPressGesture.delegate = self;
NOTE: if you have any other UIGestureRecognisers linked to your UIVIew you will have to add some checking in shouldRecognizeSimultaneouslyWithGestureRecognizer:, otherwise you can simply return YES.
I am trying to make some polygons (MKOverlayViews) tappable by adding a gesture recognizer to each of them.
I have an NSArray containing KMLParsers (from the KMLViewer sample code).
-(MKOverlayView*)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay{
for (NSString *key in kmls) {
KMLParser *kml2=[kmls objectForKey:key];
MKOverlayView *oView;
if ( (oView = [kml2 viewForOverlay:overlay]) ) {
if (layerNumber == 8) {
NSLog(#"8");
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(showZoneText:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[oView addGestureRecognizer:tap];
[tap release];
}
return oView;
}
}
return nil;
}
This code logs 8, therefore the "if" block is executed, and the layer number 8 is displayed.
However, the "showZoneText" method is never fired when I tap the polygons (an NSLog in that method never shows in the console).
-(void)showZoneText:(UITapGestureRecognizer*)recognizer{
NSLog(#"show");
}
Any help on this?
thanks,
G.
I've done the following thing:
buttonPlaylistView = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width *(urlList.count+1), 0, self.view.frame.size.width, self.view.frame.size.height)];
buttonPlaylistView.tag = 0;
UITapGestureRecognizer *doubleTap3 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[doubleTap3 setNumberOfTapsRequired:2];
[buttonPlaylistView addGestureRecognizer:doubleTap3];
[doubleTap3 release];
-(void) handleDoubleTap:(UITapGestureRecognizer *)sender{
if(sender.state == UIGestureRecognizerStateEnded)
int x = [sender tag];
return;
}
But I get SIGAGRT at this line: int x = [sender tag]; saying:
[UITapGestureRecognizer tag]: unrecognized selector sent to instance 0x61280b0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITapGestureRecognizer tag]: unrecognized selector sent to instance 0x61280b0'
NOW:What's the problem and what's the solution for this?Thanks
-(void) handleDoubleTap:(UITapGestureRecognizer *)sender
{
if(sender.state == UIGestureRecognizerStateEnded)
{
int x = [sender.view tag];
}
}
Will fix the issue.
An UITapGestureRecognizer does not have a property named tag - as you see, the sender you get is NOT the button. You have to access the buttonPlayListView directly, like
int x = [buttonPlayListView tag];
or otherwise remember which button you want to access.
Even though I'm quite sure that you're going about this the wrong way, adding a double tap gesture recognizer to a UIButton, there is a way you can still perform the task you require that shouldn't be too much work for you.
You've made the comment
and how could I remember if I create let say 100 buttons
to one of the answers, the one which highlights what the issue is that's causing your SIGBART. UIGestureRecognizer does not have a tag property.
Here's what you could do, is to iterate through all the subviews of your [self view] and find the one that has the same UIGestureRecognizer, it's not the prettiest solution, and the more subview's you have the longer the loop will take. But it'll do what you seem to be looking for, so if you're adding .
In your handleDoubleTap function you could do the following
-(void) handleDoubleTap:(UITapGestureRecognizer *)sender
{
if(sender.state == UIGestureRecognizerStateEnded)
{
int iButtonTag = -1 //This is important later to escape the below for loop as we don't need to needlessly go around in circles
for(UIView* psubView in [[self view] subviews])
{
if( [psubView isKindOfClass:[UIButton class]] )
{
UIButton* pButton = (UIButton*)psubView;
for(UIGestureRecognizer* pGesture in [pButton gestureRecognizers] )
{
if( pGesture == sender )//this is the button we're after
{
iButtonTag = [pButton tag];
break;
}
}
if( iButton != -1 )//found what we came for
{
break;
}
}
}
//do what ever it was you needed to do now that you have the views tag, or you could have kept a reference to the button etc.
}
}
That should solve your problem. Alternatively if you're going to be adding buttons to subviews of subviews it would be better to keep track of your UIButtons in an NSMutableArray , you would do this by creating a class property (or member variable) and adding the buttons to this using the 'addObject:' function of NSMutableArray. Then instead of the line
for(UIView* psubView in [[self view] subviews])
above you could exchange that for
for( UIButton* pButton in m_pMutableButtonArray )
where "m_pMutableButtonArray" is the variable name you gave to your NSMutableArray you were storing the UIButtons in. This also means you would do away with the following if isKindOfClass test on the following line.
That should fix your problem.
Why are you putting a UITapGestureRecognizer in a button? The button already handles that for you and will send you a callback, you can add a target to a button using this UIControl method
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents