UITabBarController unable to set selected Tab from Quick Action for More tabs on app startup

62 Views Asked by At

I have an app that uses a UITabBarController with 7 Tabs. Each tab is a UIViewController subclass (each embedded in a UINavigationController) that simply has a different background color in the view set in the storyboard. The TabItems are labeled Tab 1 through Tab 7 and the Title set in each NavBar is simply the Tab number. I've added some static Quick Actions in my Info.plist that allow me to jump to Tab 2, Tab 3, Tab 6 and Tab 7.

The problem I run into is when I set the selected Tab when handling the quick action in the AppDelegate all works fine for the first 4 tabs. If I select one of the Tabs listed in the More... list the app opens up only selecting the first tab in my UITabBarController. However if the app had already been running and I go to the home screen and try the Quick Action again then it is able to select any of the tabs from the More list. Any ideas?

Here is my AppDelegate code:

//  AppDelegate.swift

import UIKit

@UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate 
{

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        // handle quick actions
        if let shortcutItem =
        launchOptions?[UIApplicationLaunchOptionsKey.shortcutItem]
            as? UIApplicationShortcutItem {

            let _ = handleShortcut(shortcutItem: shortcutItem)
            return false
        }

        return true
    }

    func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {

        completionHandler(handleShortcut(shortcutItem: shortcutItem))
    }

    private func handleShortcut(shortcutItem: UIApplicationShortcutItem) -> Bool {
        let shortcutType = shortcutItem.type
        guard let shortcutIdentifier = ShortcutIdentifier(fullIdentifier: shortcutType) else {
            return false
        }

        switch shortcutIdentifier {
        case ShortcutIdentifier.OpenTab2: fallthrough
        case ShortcutIdentifier.OpenTab3: fallthrough
        case ShortcutIdentifier.OpenTab6: fallthrough
        case ShortcutIdentifier.OpenTab7:
            return selectTabBarItem(forIdentifier: shortcutIdentifier)
        }
    }

    private func selectTabBarItem(forIdentifier identifier: ShortcutIdentifier) -> Bool {
        if let tabBarController = self.window?.rootViewController as? CustomTabBarController
        {

            switch (identifier)
            {
            case .OpenTab2:
                tabBarController.selectedIndex = tabDictionary["OpenTab2"]!
            case .OpenTab3:
                tabBarController.selectedIndex = tabDictionary["OpenTab3"]!
            case .OpenTab6:
                tabBarController.selectedIndex = tabDictionary["OpenTab6"]!
            case .OpenTab7:
                tabBarController.selectedIndex = tabDictionary["OpenTab7"]!
            }
        }
        return true
    }

    // Integer in dictionary denotes tab number (zero based)
    private let tabDictionary = ["OpenTab2": 1, "OpenTab3": 2, "OpenTab6": 5, "OpenTab7": 6]

    enum ShortcutIdentifier: String {
        case OpenTab2
        case OpenTab3
        case OpenTab6
        case OpenTab7

        init?(fullIdentifier: String) {
            guard let shortIdentifier = fullIdentifier.components(separatedBy: ".").last else {
                return nil
            }
            self.init(rawValue: shortIdentifier)
        }
    }

}
1

There are 1 best solutions below

0
user7705986 On

I found the following link (http://jakzaprogramowac.pl/pytanie/18417,select-index-greater-than-3-for-uitabbarcontroller-at-app-launch-not-working) that seemed to answer my question. I hope this helps others.

I added the following code to the beginning of AppDelegate DidFinishLaunchingWithOptions to initially select the first tab and call layoutIfNeeded() on the tabBarController's View:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
{
    // Override point for customization after application launch.

    // initially select first tab so more selection works from quick    actions - fixup
    if let tabBarController = self.window?.rootViewController as? CustomTabBarController
    {
        tabBarController.selectedIndex = 0
        tabBarController.view.layoutIfNeeded()
    }

    // handle quick actions
    if let shortcutItem =
    launchOptions?[UIApplicationLaunchOptionsKey.shortcutItem]
        as? UIApplicationShortcutItem {

        let _ = handleShortcut(shortcutItem: shortcutItem)
        return false
    }

    return true
}