I love the swipe pack thats inherited from embedding your views in a UINavigationController. Unfortunately i cannot seem to find a way to hide the Naviga
Some people have had success by calling the setNavigationBarHidden method with animated YES instead.
The answer of Hunter Monk is really awesome, but unfortunately in iOS 13.3.1, it does not work.
I will explain another way to hide UINavigationBar and not lose swipe to back gesture.
I have tested on iOS 13.3.1 and 12.4.3 and it works.
You need to create a custom class of UINavigationController and set that class for UINavigationController in Storyboard
Do NOT hide the NavigationBar on the Storyboard
Example on Storyboard:
And finally, put this: navigationBar.isHidden = true in viewDidLoad of CustomNavigationController class.
Make sure, do NOT use this method setNavigationBarHidden(true, animated: true) for hiding the NavigationBar.
import UIKit
class CustomNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
navigationBar.isHidden = true
}
}
Here is how to disable de gesture recognizer when user slides out of the ViewController. You can paste it on your viewWillAppear() or on your ViewDidLoad() methods.
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
In my case, to prevent strange effects
Root view controller
override func viewDidLoad() {
super.viewDidLoad()
// Enable swipe back when no navigation bar
navigationController?.interactivePopGestureRecognizer?.delegate = self
}
// UIGestureRecognizerDelegate
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if let navVc = navigationController {
return navVc.viewControllers.count > 1
}
return false
}
You can do it with a Proxy Delegate. When you are building the navigation controller, grab the existing delegate. And pass it into the proxy. Then pass all delegate methods to the existing delegate except gestureRecognizer:shouldReceiveTouch: using forwardingTargetForSelector:
Setup:
let vc = UIViewController(nibName: nil, bundle: nil)
let navVC = UINavigationController(rootViewController: vc)
let bridgingDelegate = ProxyDelegate()
bridgingDelegate.existingDelegate = navVC.interactivePopGestureRecognizer?.delegate
navVC.interactivePopGestureRecognizer?.delegate = bridgingDelegate
Proxy Delegate:
class ProxyDelegate: NSObject, UIGestureRecognizerDelegate {
var existingDelegate: UIGestureRecognizerDelegate? = nil
override func forwardingTargetForSelector(aSelector: Selector) -> AnyObject? {
return existingDelegate
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return true
}
}
There is a really simple solution that I tried and works perfectly, this is in Xamarin.iOS but can be applied to native too:
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
this.NavigationController.SetNavigationBarHidden(true, true);
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
this.NavigationController.SetNavigationBarHidden(false, false);
this.NavigationController.NavigationBar.Hidden = true;
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
this.NavigationController.SetNavigationBarHidden(true, false);
}