UISplitViewController swipe gesture interferes with other swipe gesture - ios

I'm using a UISplitViewController and one of the detail view controllers contains a view which has a UIPanGestureRecognizer added to it. When I swipe this view in the detail view controller, the gesture is recognized, but the swipe gesture recognizer of the split view controller interferes with it; the master view controller is displayed and the gesture recognizer from the detail controller is ignored.
Implementing and debugging the shouldRecognizeSimultaneouslyWithGestureRecognizer method from the UIGestureRecognizerDelegate shows two UIPanGestureRecognizer objects: one from the detail view controller and the one from the split view controller, so I'm certain they are interfering with each other.
When I set presentsWithGesture = NO on the split view controller, the gesture recognizer inside the detail view controller does work. But that disables the gesture recognizer on the split view controller, so it's not really a solution to the problem.
I've also tried disabling the gesture recognizer on the split view controller, only when I need the other gesture recognizer to work, but it seems that it is not possible to set presentsWithGesture once the split view controller has become visible.
I've also tried to disable the default gesture on the split view controller and adding a custom gesture which I can control, but it didn't work. I tried using the target and action from the split view controller barbutton on the gesture, but it doesn't work. Calling toggleMasterVisible: on the split view controller isn't an option either because it's part of the private api.
Does anyone have any suggestions on how to handle this?

I would suggest that you disable the UISplitViewController pan gesture when you need the other one to work. This should do it:
for (UIGestureRecognizer* recognizer in [splitViewController gestureRecognizers]) {
if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
[recognizer setEnabled:NO];
}
}
You probably don't want to search for it each time, so I would store a reference to that gesture recognizer when the view loads, then just disable and enable as appropriate:
on viewDidLoad:
for (UIGestureRecognizer* recognizer in [splitViewController gestureRecognizers]) {
if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
[self setSplitViewPanGesture:recognizer];
}
}
later:
[self.splitViewPanGesture setEnabled:NO];
and later:
[self.splitViewPanGesture setEnabled:YES];

Related

Prevent a swipe gesture while another UIViewController is present

I have an app that has a mode that users enter into when editing a geographic feature. While in this editing mode, I present a view controller with an embedded tableview that is inset from the view controller's frame. The background of this view controller has an alpha of 0.5 so the underlying view is still partially visible outside of the inner table view, though grayed out by the semi-opaque view controller on top. There is a button on the underlying view controller that is used to slide the view to the right when not in editing mode.
While the editing view controller is active, this button to activate the slider is disabled, which is desired behavior. However, users can also swipe the view to the right which achieves the same things a the button. i would like to disable this swipe feature while the editing view controller is present.
So I guess my question is: how can I disable a swipe gesture when a certain view controller is present?
You can use the gestureRecognizerShouldBegin: delegate method. If the detected gesture is that particular swipe gesture (i.e. theGesture) and that certain view controller is present (i.e. theView), tell the gesture not to begin, ex:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer == theGesture && theView.window != nil) {
return NO;
} else {
return YES;
}
}

Tap Gesture Recognizer and UIControl

I've a view controller with UISegmentedControl and UITableView as its children. In -viewDidLoad I create a UITapGestureRecognizer and add it to the controller's main view.
When I tap on, for instance, a cell of the table view, the tap gesture recognizer's action is being called and it prevents receiving touches to the table view (that's ok as tapRecognizer.cancelsTouchesInView == YES).
However, the issue is that when I tap on the segmented control, the tap gesture recognizer's action is not being called. Why is it so? How to make the tap gesture recognizer the "top" object which handles touches?
Thanks,
Adam

removing childviewcontroller disables gestures in parentviewcontroller when the parentviewcontroller is re-presented

in iOS when I add a childviewcontroller, then remove it - all gestures that overlap have been disabled.
For example the parentviewcontroller has a 'longtap' gesture, and the childviewcontroller has a 'longtap' gesture.
the parent views longtap gesture works.
then i do addchildviewcontroller and that VCs longtap gesture works.
then i call removeFromParentViewController
and the original viewcontroller's view which used to respond to longtap gestures has had its gesture disabled.
(I could cycle through all the gestures and 'renable' them again - my question is why is the longtap gesture getting disabled when i add, and then remove a childviewcontroller - I'm doing everything standard, ie.
[_parentVC addChildViewController:alertVC];
[_parentVC willMoveToParentViewController:alertVC];
[_parentVC.view addSubview:alertVC.view];
then
[alertVC.view removeFromSuperview];
[alertVC removeFromParentViewController];
[alertVC willMoveToParentViewController:_parentVC];
Wow.
A lot of code here.
Looks like the gesture was manually disabled after the event took place. So the gesture being disabled had nothing to do with adding childviewcontrollers.

UIPageViewController crashes when holding down a button while it's animating

I have UIPageViewController that animates programatically. The problem is that the view controllers inside it has UIButtons inside them. When I hold down a button and wait until the UIPageViewController animates, the app crashes with the error:
'Failed to determine navigation direction for scroll'
What I think I need to do is to somehow fake that the user releases the button before the UIPageviewController animates.
However, [self.button sendActionsForControlEvents:UIControlEventTouchCancel]; doesn't seem to do the trick. Neither do UIControlEventTouchUpInside.
Is there a better way do to it or am I using sendActionsForControlEvents wrong?
All sendActionsForControlEvents: does is call any methods you've assigned to the control events passed in for the button. It doesn't call any internal methods to programmatically lift up touches or anything like that.
Right before you programmatically animate your page view controller, try using this method to effectively cancel any touches on the pan gesture recognizer of the page view controller's internal scroll view:
- (void)cancelPanGestureTouchesOfPageViewController:(UIPageViewController *)pageVC
{
// Since UIPageViewController doesn't provide any API to access its scroll view,
// we have to find it ourselves by manually looping through its view's subviews.
for (UIScrollView *scrollView in pageVC.view.subviews) {
if ([scrollView isKindOfClass:[UIScrollView class]]) {
// We've found the scroll view, so use this little trick to
// effectively cancel any touches on its pan gesture recognizer
BOOL enabled = scrollView.panGestureRecognizer.enabled;
scrollView.panGestureRecognizer.enabled = !enabled;
scrollView.panGestureRecognizer.enabled = enabled;
}
}
}
(Note that this is messing with the internal view hierarchy of UIPageViewController, so this method is kind of ugly and may break in the future. I generally don't recommend doing stuff like this, but I think in this instance it should be okay.)

Swipe gesture between view controllers in storyboards

I am looking to add a left and right swipe gesture to change between view controllers, is this possible and is there an easy way to do this in storyboards? Thanks :)
Storyboards allow you to set up segues between two view controllers. I would say start by attaching segues between the views, give it an identifier.
Then use something like
UISwipeGestureRecognizer * recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(myRightAction)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self addGestureRecognizer:recognizer];
to add a swipe recognizer to a view.
Then in the myRightAction method you'd want to do your segue call like
[self performSegueWithIdentifier: #"MySegue" sender: self];
to go to a view or dismiss it to leave the view.
You can use Navigation View Controllers to have a right and left transition animation. You can also make custom segues.
on Xcode 5 it is simpler, less code needed:
storyboard -> utility panel -> object Library -> drag and drop the Swipe Gesture Recognizer inside your scene
you MUST drag it into the view itself(where the background color appears) so you can see this connection: referencing outlet collections -> view
add the delegate by dragging the delegate's connection pin to the viewController
Show assistant editor -> add an action by ctrl + drag and drop on your delegate class viewController.m
inside that action write
[self performSegueWithIdentifier:#"mySegueIdentifier" sender:self];
Oops. Posted a comment on accident. Take a look at this answer: https://stackoverflow.com/a/14125580/1126783. You could just use a swipe gesture instead of buttons, and it uses storyboards.

Resources