[Solved] Swipe back gesture not working in iOS 17 when NavBar is hidden – Swift UI – Ios

by
Maya Patel
axios ios17 swiftui-ontapgesture uigesturerecognizer uikit

Quick Fix: The issue can be resolved by dynamically hiding and un-hiding the navigation bar in the parent view controller using the help of a shared AppState.

The Problem:

A custom extension for enabling swipe back gestures in SwiftUI, which previously worked on iOS 16, is no longer functioning after updating to iOS 17 beta. The extension aims to allow swipe back gestures even when the navigation bar is hidden. The navigation bar is hidden using .navigationBarHidden(true) on a view. However, upon attempting to swipe back on the affected view, the gesture is unresponsive, and the view remains unchanged. Testing this code on iOS 16 confirms its functionality, indicating that the issue specifically arises with iOS 17 beta. Additional information includes Xcode version and the absence of significant code changes. Assistance is sought in resolving this issue or obtaining alternative approaches compatible with iOS 17.

The Solutions:

Solution 1: Use a custom UINavigationController subclass to manage the navigation bar visibility

In this approach, you create a custom UINavigationController subclass that overrides the viewWillLayoutSubviews() method to hide or show the navigation bar based on a certain condition. Here’s an example:

import UIKit

class CustomNavigationController: UINavigationController {
    override open func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

        // Hide the navigation bar when the condition is met
        navigationBar.isHidden = condition

        // Optionally, you can also adjust the frame of the child view controller's view to account for the hidden navigation bar
        if navigationBar.isHidden {
            let childViewFrame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height)
            childViewControllers.first?.view.frame = childViewFrame
        }
    }
}

To use this custom navigation controller, you would assign it to the navigation controller property of your SwiftUI view like this:

NavigationView {
    // Your view content here
}
.navigationViewStyle(StackNavigationViewStyle()) // Use the stack navigation style for a consistent UI
.frame(maxWidth: .infinity, maxHeight: .infinity) // Set the frame to fill the entire screen
.background(Color.white) // Set a background color if desired
.navigationBarTitleDisplayMode(.inline) // Optionally, set the navigation bar title display mode
.navigationBarHidden(true) // Hide the navigation bar initially
.navigationBarItems(leading: /* Your leading bar button items */, trailing: /* Your trailing bar button items */) // Optionally, add navigation bar items
.navigationController(CustomNavigationController()) // Assign the custom navigation controller

This approach allows you to hide the navigation bar programmatically while still maintaining the swipe back gesture functionality, even on iOS 17. The condition you specify in the viewWillLayoutSubviews() method can be anything you need for your specific use case.

Q&A

How to enable swipe back gesture after hiding navBar in iOS 17?

Try using the UINavigationController’s extension with viewWillLayoutSubviews method.

How to hide navBar programatically in iOS 17?

Use AppState class and set AppState.shared.navHideen to true to hide the navBar.

Video Explanation:

The following video, titled "How to enable gesture navigation and hide navigation bar on any ...", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

the app was working fine until android 11, now i can't hide the navigation bar despite following the steps above. do you know a way around ...