Search code examples
iosswiftios13

UITableView's scroll view insets not adjusting in iOS 13 devices


I have a tab bar controller that shows 5 tabs. It shows perfectly in iOS 12 or earlier as shown here

here.

But if I run the same in iOS 13, the design is totally messed up

this.

It totally loses the scroll view insets, and it is also not adjusting the bottom insets of my menus table view. some of the menus are hidden in the bottom. they are not scrolling up. and this is the code that I'm using in UITabBarController

override func viewDidLoad() {
    super.viewDidLoad()
    delegate = self



    guard let user = user else {
        appDelegate.instituteSelectionView()
        return
    }

    var dashBoard: UINavigationController
    var menus: UINavigationController? = nil

    // Creating all the view controllers for tabs.
    if user.role.caseInsensitiveCompare("student") == .orderedSame {
        let dashBoardVC = mainStoryBoard.instantiateViewController(withIdentifier: "DashboardVC") as! DashboardVC
        dashBoardVC.menus = ContentProvider.getMenus()
        dashBoardVC.school = user.school
        dashBoard = UINavigationController(rootViewController: dashBoardVC)
        dashBoard.navigationBar.prefersLargeTitles = true
    } else {
        let dashBoardVC = mainStoryBoard.instantiateViewController(withIdentifier: "DashboardWidgetsTableViewController") as! DashboardWidgetsTableViewController
        dashBoardVC.user = user
        dashBoardVC.title = "Dashboard"
        dashBoard = UINavigationController(rootViewController: dashBoardVC)

        let menusVC = mainStoryBoard.instantiateViewController(withIdentifier: "MenusTableViewController") as! MenusTableViewController
        menusVC.setMenus(ContentProvider.getMenusForStaff())
        menus = UINavigationController(rootViewController: menusVC)
    }
    dashBoard.tabBarItem = UITabBarItem(title: "Dashboard", image: #imageLiteral(resourceName: "dashboard"), tag: 0)

    if menus != nil {
        menus?.navigationBar.prefersLargeTitles = true
        menus?.tabBarItem = UITabBarItem(title: "Menus", image: #imageLiteral(resourceName: "menu-1"), tag: 1)
    }
    let notificationVC = mainStoryBoard.instantiateViewController(withIdentifier: "NotificationsTabTableViewController") as! NotificationsTabTableViewController
    notificationVC.user = user
    let notification = UINavigationController(rootViewController: notificationVC)
    notification.tabBarItem = UITabBarItem(title: "Notifications", image: #imageLiteral(resourceName: "bell"), tag: 3)
    notification.tabBarItem.badgeValue = user.badge > 0 ? String(user.badge) : nil
    notification.navigationBar.prefersLargeTitles = true

    let settingsVC = mainStoryBoard.instantiateViewController(withIdentifier: "SettingsTabTableViewController") as! SettingsTabTableViewController
    settingsVC.user = user
    let settings = UINavigationController(rootViewController: settingsVC)
    settings.tabBarItem = UITabBarItem(title: "Settings", image: #imageLiteral(resourceName: "settings"), tag: 4)
    settings.navigationBar.prefersLargeTitles = true

    let accountsVC = mainStoryBoard.instantiateViewController(withIdentifier: "AccountsTableViewController") as! AccountsTableViewController
    let accounts = UINavigationController(rootViewController: accountsVC)
    accounts.tabBarItem = UITabBarItem(title: "Accounts", image: #imageLiteral(resourceName: "user_group_man_man"), tag: 5)
    accounts.navigationBar.prefersLargeTitles = true


    mViewControllers = [dashBoard, notification, settings, accounts]
    if menus != nil {
        mViewControllers.insert(menus!, at: 1)
    }

    // Adding logo and profile button to navigation bar of each view controller.
    for vc in mViewControllers {
        if let nVC = vc as? UINavigationController, let vc = nVC.topViewController {
            let logo = UIImageView(image: #imageLiteral(resourceName: "educare logo"))
            logo.contentMode = .scaleAspectFill
            logo.clipsToBounds = true
            logo.widthAnchor.constraint(equalToConstant: 24).isActive = true
            logo.heightAnchor.constraint(equalToConstant: 24).isActive = true

            let profileButton = UIButton(type: .custom)
            profileButton.widthAnchor.constraint(equalToConstant: 24).isActive = true
            profileButton.heightAnchor.constraint(equalToConstant: 24).isActive = true
            profileButton.imageView?.layer.cornerRadius = 12
            if #available(iOS 13.0, *) {
                let image = UIImage(systemName: "person.crop.circle")
                profileButton.sd_setImage(with: URL(string: user.image), for: .normal, placeholderImage: image)
            } else {
                profileButton.sd_setImage(with: URL(string: user.image), for: .normal, placeholderImage: #imageLiteral(resourceName: "user_circle"))
            }

            profileButton.addTarget(self, action: #selector(openProfile), for: .touchUpInside)

            let logoButtonItem = UIBarButtonItem(customView: logo)
            let profileButtonItem = UIBarButtonItem(customView: profileButton)

            vc.navigationItem.leftBarButtonItem = logoButtonItem
            vc.navigationItem.rightBarButtonItems = [profileButtonItem]
        }
    }
    setViewControllers(mViewControllers, animated: true)
}

Update: Actually the first view controller in the tab bar controller renders correctly but the rest of the view controllers have that ugly navigation bar.


Solution

  • I Solved the problem. turns out it was the transition animation (from the initial view controller to the main tab bar controller) that was causing the problem. So i changed the code from this

    if animated {
            UIView.transition(from: (window?.rootViewController?.view)!, to: viewController.view, duration: duration, options: animationOptions) { (completed) in
                if completed {
                    self.window?.rootViewController = viewController
                    self.window?.makeKeyAndVisible()
                }
            }
        } else {
            self.window?.rootViewController = viewController
            self.window?.makeKeyAndVisible()
        }
    

    to this

    guard let window = UIApplication.shared.keyWindow else { return }
        window.rootViewController = viewController
        window.makeKeyAndVisible()
        if animated {
            UIView.transition(with: window, duration: duration, options: animationOptions, animations: {})
        }