Gesture recogniser does not works on tableView - objective-c

The tableView was done programatically, and is listen to delegates .
the gestures :
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTapOnTableView:)];
[self.tableView addGestureRecognizer:tap];
-(void) didTapOnTableView:(UIGestureRecognizer*) recognizer
{
NSLog(#"ffff");
}
does not being called.

The problem is that UITableView has gesture recognizers of its own and they conflict with the ones you're adding. You can allow simultaneous processing of gesture recognizers by conforming your UIViewController subclass to <UIGestureRecognizerDelegate> protocol and implementing the following method gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:.
On the other hand, what you are trying to do is most probably wrong. Try using a UIButton object instead of the gesture recognizer, in 99% of the time that'll be enough.

this should be working, unless you are not tapping on the tableview, check is the tableview showing properly, or add break point to check is the gesture recogniser is added

Try to enable multitouch on the view using interface builder or this property multipleTouchEnabled.
if thats not what you are looking for you can use the delegate function for receiving touches:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return YES;
}
(if you go to the header of this file you can find similar delegates that might help)

Related

Gesture recognizer for UIView no longer working after connecting the view to IBOutlet

I have a custom button which is basically a UIView with a gesture recognizer. Both the UIView and it's gesture recognizer were put together in interface builder.
The action for the gesture recognizer triggers a segue and opens a view controller. This works just fine.
I created an IBOutlet for this UIView button, but it seems that when I hook it up the action of triggering the segue and opening the next view controller stops working, even though the gesture recognizer and action are still showing up in interface builder.
Why does the gesture recognizer stop working when I hook the UIView up to an IBOutlet?
Check that the User Interaction is enabled for that view in the id-inspector or not. Or check there are no extra connection are shown in the connection inspector
Why you add gesture in your UIView? Simple make your UIView to UIControl class from storyboard and you can simple add action like button on it using storyboard
Or by adding gesture you can do it
connect IBOutlet of your view with UIView
then add gesture in it
-(void)viewDidLoad {
//The setup code (in viewDidLoad in your view controller)
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSingleTap:)];
[vw_button addGestureRecognizer:singleFingerTap];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
//The event handling method
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
CGPoint location = [recognizer locationInView:[recognizer.view superview]];
//Do stuff here...
}

UIGestureRecognizer blocking tableview scrolling

I have a table with static cells. One of these cells has a view in it with a pan gesture recogniser on it.
When I am scrolling down my tableview, when I get to the cell with the view with pan gesture recogniser, scrolling doesn't seem to work. If I touch outside the view (to the side or top or bottom) it works and I can scroll. I have an if statement in my gesturerecognizer that tests whether a certain area has been touched, and if so performs an action.
I have looked at this issue (http://stackoverflow.com/questions/3295239/uigesturerecognizer-blocking-table-view-scrolling) but setting cancelsTouchesInView to NO didn't work, I don't have anywhere setting the state property and using the method - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
I don't know where to get the 'otherGestureRecognizer' from or what object to call that method on.
I'm assuming I wan't to put my gesture recogniser as the first argument, and the tableview's scroll gesture recogniser as the otherGestureRecogniser, is that correct? If so, how do I get that?
UIPanGestureRecognizer *windPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(moveWindHandle:)];
[self.windRangeView addGestureRecognizer:windPanGesture];
Then in my moveWindHandle:
-(void)moveWindHandle:(UIPanGestureRecognizer *)gesture
{
gesture.cancelsTouchesInView = NO;
isMovingHandle = [self isPoint:startedTouchAt insideHandle:_toHandleWindImageView];
if(isMovingHandle) {
if(gesture.state == UIGestureRecognizerStateBegan) {
//do stuff
}
}
else
{
//i want it to ignore this gesture and just scroll like normal if that is what hte user did
}
}
I have set the tableviewcontroller as a UIGestureRecognizerDelegate, but I don't know what to do with that.
You would not be the one calling -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:. That method is called by the system. You need to set your table view controller as the delegate for your window pan gesture.
windPanGesture.delegate = self;
At that point, when you do the pan, the system will call the delegate method -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: with your gesture recognizer as one argument and the scroll view's gesture recognizer as the other.
Update
You may also want to implement the -gestureRecognizerShouldBegin: method and return NO if you are not in one of the certain areas.

UIPageViewController Traps All UITapGestureRecognizer Events

It's been a long day at the keyboard so I'm reaching out :-)
I have a UIPageViewController in a typical implementation that basically follows Apple's standard template. I am trying to add an overlay that will allow the user to do things like touch a button to jump to certain pages or dismiss the view controller to go to another part of the app.
My problem is that the UIPageViewController is trapping all events from my overlay subview and I am struggling to find a workable solution.
Here's some code to help the example...
In viewDidLoad
// Page creation, pageViewController creation etc....
self.pageViewController.delegate = self;
[self.pageViewController setViewControllers:pagesArray
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:NULL];
self.pageViewController.dataSource = self;
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
// self.overlay being the overlay view
if (!self.overlay)
{
self.overlay = [[MyOverlayClass alloc] init]; // Gets frame etc from class init
[self.view addSubview:self.overlay];
}
This all works great. The overlay gets created, it gets show over the top of the pages of the UIPageViewController as you would expect. When pages flip, they flip underneath the overlay - again just as you would expect.
However, the UIButtons within the self.overlay view never get the tap events. The UIPageViewController responds to all events.
I have tried overriding -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch per the suggestions here without success.
UIPageViewController Gesture recognizers
I have tried manually trapping all events and handling them myself - doesn't work (and to be honest even if it did it would seem like a bit of a hack).
Does anyone have a suggestion on how to trap the events or maybe a better approach to using an overlay over the top of the UIPageViewController.
Any and all help very much appreciated!!
Try to iterate through UIPageViewController.GestureRecognizers and assign self as a delegate for those gesture and implement
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
Your code may be like this:
In viewDidLoad
for (UIGestureRecognizer * gesRecog in self.pageViewController.gestureRecognizers)
{
gesRecog.delegate = self;
}
And add the following method:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (touch.view != self.pageViewController.view]
{
return NO;
}
return YES;
}
The documented way to prevent the UIPageViewController from scrolling is to not assign the dataSource property. If you assign the data source it will move into 'gesture-based' navigation mode which is what you're trying to prevent.
Without a data source you manually provide view controllers when you want to with setViewControllers:direction:animated:completion method and it will move between view controllers on demand.
The above can be deduced from Apple's documentation of UIPageViewController (Overview, second paragraph):
To support gesture-based navigation, you must provide your view controllers using a data source object.

Trouble with gesture recognizers in subviews

I'm having a rather basic problem, I've looked around (here, google, etc) and haven't found a solution for this:
In my View Controller's viewDidLoad, I have this:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(myfunc:)];
//I have a UIScrollView named "containerView"
//here's some code that creates an UIView in a variable named "myView"
//this works fine, I can see "myView" when I run it
[containerView addSubview:myView];
[myView addGestureRecognizer:longPress];
and then I have this function in the same class:
- (void)myfunc:(UIRotationGestureRecognizer *)recognizer
{
NSLog(#"hola!"); //never runs
}
The call to NSLog never runs. What am I doing wrong?
EDIT
Some extra info: it seems no touch events are ever sent to the subview. However, I tried adding an UIView with a button inside, all in the UIScrollView, and the button receives the touch event just fine, so the problem is only with programmatically added subviews.
Strangely enough, adding a "container" UIView inside the UIScrollView, and then the other subviews inside this container, made it work. Now touch events are sent to the subviews.
How can a superview interecept a touch sequence before any of its subviews?
TLDR:
[containerView setCanCancelContentTouches:NO];
do it just as you add the gesture recogniser to the scroll view.
also look into
[containerView setDelaysContentTouches:NO];
If the above behaviour isn't quite right.
for more info:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html
I think on myFunc you must do somethings like that:
switch (reconiger.state)
{
case UIGestureRecognizerBegin:
//Do something when start recognizer
break;
case UIGestureRecognizerEnd:
//Do something when end recognizer
break;
}

Continuous scrolling between UIPanGestureRecognizer and re-enabled UIScrollView

I've got a UIScrollView with paging enabled, and I've added my own UIPanGestureRegonizer to it. Under certain instances, my view controller will set scrollview.scrollEnabled = NO, and then add the pan gesture recognizer to it (I'm not using the scrollview's own recognizer).
So, scrolling is disabled but I'm waiting for user touches from my gesture recognizer. When it recognizes, it calls its action in which I re-enable scrolling.
The problem is, while the user still has a finger down, my scrollview doesn't track with the finger. It doesn't start scrolling until the finger is lifted and then dragged again. So my gesture recognizer is swallowing all the touches and not forwarding any to the scrollview.
I've tried toggling panGestureRecognizer.cancelsTouchesInView = NO; but it doesn't seem to have any effect (I'm currently removing this recognizer as soon as I re-enable scrolling but whether I do this or not doesn't solve my problem). I've also looked into the delays... properties of UIGestureRecognizer but they don't seem to be helping, either.
Any ideas? How can I get these events to continue to forward to my scrollview?
The answer is a bit easier if you are only targeting iOS 5 and up, because in that case you really ought to reuse the UIScrollView panGestureRecognizer property.
In any case, the key step is to NOT reuse scrollEnabled, but instead to subclass UIScrollView, create your own property to manage this state, and override setContentOffset:.
- (void) setContentOffset:(CGPoint)contentOffset
{
if(self.programaticScrollEnabled)
[super setContentOffset:contentOffset];
}
Here's one possible iOS 4+ Solution:
Subclass UIScrollView (or subclass another subclass of UIScrollView, depending on your needs).
Override all the initializers to ensure your setup code is called.
Declare the BOOL property and override setContentOffset: as described above.
In your setup code, set up a UIPanGestureRecognizer and set your state variable to allow programatic scrolling (assuming that's the default state you want):
panRecognizer = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)] autorelease];
//These properties may change according to your needs
panRecognizer.cancelsTouchesInView = NO;
panRecognizer.delaysTouchesBegan = NO;
panRecognizer.delaysTouchesEnded = NO;
[self addGestureRecognizer:panRecognizer];
panRecognizer.delegate = self;
self.programaticScrollEnabled = YES;
Manage which gestures can occur simultaneously. In my case:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Turn programatic scrolling back on wherever you need it. For example:
- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer
{
self.programaticScrollEnabled = YES;
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
self.programaticScrollEnabled = YES;
return YES;
}