Fatal Exception: NSInternalInconsistencyException Attempting to select a view controller that isn't a child! (null)

When call: [UITabBarController setViewControllers:animated:] It crashed and raise an Fatal Exception: Fatal Exception: NSInternalInconsistencyException Attempting to select a view controller that isn't a child! (null)

the crash stack is: Fatal Exception: NSInternalInconsistencyException 0 CoreFoundation 0x8408c __exceptionPreprocess 1 libobjc.A.dylib 0x172e4 objc_exception_throw 2 Foundation 0x82215c _userInfoForFileAndLine 3 UIKitCore 0x38a468 -[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] 4 UIKitCore 0x3fa8a4 -[UITabBarController _setSelectedViewController:performUpdates:] 5 UIKitCore 0x3fa710 -[UITabBarController setSelectedIndex:] 6 UIKitCore 0x8a5fc +[UIView(Animation) performWithoutAnimation:] 7 UIKitCore 0x3e54e0 -[UITabBarController _setViewControllers:animated:] 8 UIKitCore 0x45d7a0 -[UITabBarController setViewControllers:animated:]

And it appear sometimes, what's the root cause?

It isn't immediately clear what the issue may be with the stack trace. Could you please file a feedback with a sample project that reproduces this issue and reply with the Feedback number? It'd help us investigate this issue to determine the root cause.

Hi, After research, we have found that the crash appear in iOS 18 and below iOS 18, it works well. And I write a simple demo that can reproduce it. The code is:

AppDelegate:
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        let window = UIWindow()
        
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let tabBarViewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarVC") as! TabBarViewController
        tabBarViewController.rebuildTabBar()
        
        window.rootViewController = tabBarViewController

        self.window = window
        window.makeKeyAndVisible()
        
        return true
    }
TabBarViewController:
class TabBarViewController: UITabBarController {
    private let vc1 = UIViewController()
    private let vc2 = UIViewController()
    private let vc3 = UIViewController()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // not crash
        setViewControllers([vc1], animated: false)
        
        //will crash
        setViewControllers([vc2], animated: false)
    }
    
    public func rebuildTabBar() {
        setViewControllers([vc1, vc2, vc3], animated: false)
    }
}

We use UIStoryboard to create a TabBarViewController instance, ViewController use UIStoryboard will not call viewDidLoad at the beginning, and after call UITabBarController's rebuildTabBar method to setViewControllers, if TabBarViewController's view is not load, it will call viewDidLoad again. In viewDidLoad, we call setViewControllers again, if the viewControllers parameter array's first vc is different with the setting in rebuildTabBar, it crashed.

could you please help to explain the reason, thank you.

Fatal Exception: NSInternalInconsistencyException Attempting to select a view controller that isn't a child! (null)
 
 
Q