Search code examples
iosuitabbarcontrollerios-simulatoruitabbarchildviewcontroller

Child View Controller don't appear on device


I'v developed custom UITabbarController with my own tabbar layout. I've got a set of UIViewController, that i instantiate from stroryboard like this :

class func instantiateMainViewControllers () -> Array<UIViewController>
{
    var controllersArray = Array<UIViewController>()
    let storyboard = UIStoryboard(name: "Main", bundle: nil)

    let feedVC = storyboard.instantiateViewControllerWithIdentifier(BL_UIConst.kFeedControllerIdentifier)


    controllersArray.append(feedVC)

    let exploreVC = storyboard.instantiateViewControllerWithIdentifier(BL_UIConst.kExploreControllerIdentifier)
    controllersArray.append(exploreVC)

    let cameraVC = storyboard.instantiateViewControllerWithIdentifier(BL_UIConst.kCameraControllerIdentifier)
    controllersArray.append(cameraVC)

    let chatVC = storyboard.instantiateViewControllerWithIdentifier(BL_UIConst.kChatControllerIdentifier)
    controllersArray.append(chatVC)

    let profileVC = storyboard.instantiateViewControllerWithIdentifier(BL_UIConst.kProfileControllerIdentifier)
    controllersArray.append(profileVC)

    return controllersArray
}

And than assign to view controllers array of my custom UITabbarController. Switching between controllers works as follows ( custom tabbar controller has presentationView UIView on it to display child controller ) :

private func displayViewController ( atIndex index : Int ) -> Void
{
    let controller = viewControllersArray[index]

    if ( presentationView.subviews.count > 0 )
    {
        let presentedView = presentationView.subviews[0]

        for ( var i = 0 ; i < viewControllersArray.count ; i++ )
        {
            let localController = viewControllersArray[i]

            if ( localController.view == presentedView )
            {
                localController.willMoveToParentViewController(nil)
                localController.view.removeFromSuperview()
                localController.removeFromParentViewController()

                break
            }
        }
    }

   self.addChildViewController(controller)
   controller.view.bounds = self.presentationView.bounds
   controller.view.frame = CGRectMake(0.0, 0.0, presentationView.frame.size.width, presentationView.frame.size.height - 10)
   presentationView.addSubview(controller.view)
}

And i make initial setup of controllers array ( selecting first one and calling displayViewController procedure ) at viewDidAppear function. First controller is a table view.

Than a very magic thing happens. On simulator ( iPhone 6s, iOS 9.2 - on the screenshot there is a small autolayout issue - tabbar has still static 320.0 size and iPhone 5s, iOS 9.2 ) -

enter image description here

BUT

On device ( iPhone 5, iOS 9.2 ) i've got this on the screen ( even tab bar is in its initial state - every segment is selected ) and nothing on the screen -

enter image description here

I've debug every frame of child view controllers, printed frames of subviews - everything is correct. What can cause this issue? Thanks.

EDIT

I'm managing tab bar in following way. It belongs to main Tab bar view controller. And that controller has the following configuration method -

private func setUpTabBar ( forSelectedActionSignContainer imageView : UIImageView ) -> Void
{
    var viewControllerIndex = 0

    if ( imageView == feedSign )
    {
        feedSign.hidden = false
        exploreSign.hidden = true
        cameraSign.hidden = true
        chatSign.hidden = true
        profileSign.hidden = true
        viewControllerIndex = 0
    }
    if ( imageView == exploreSign )
    {
        feedSign.hidden = true
        exploreSign.hidden = false
        cameraSign.hidden = true
        chatSign.hidden = true
        profileSign.hidden = true
        viewControllerIndex = 1
    }
    if ( imageView == cameraSign )
    {
        feedSign.hidden = true
        exploreSign.hidden = true
        cameraSign.hidden = false
        chatSign.hidden = true
        profileSign.hidden = true
        viewControllerIndex = 2
    }
    if ( imageView == chatSign )
    {
        feedSign.hidden = true
        exploreSign.hidden = true
        cameraSign.hidden = true
        chatSign.hidden = false
        profileSign.hidden = true
        viewControllerIndex = 3
    }
    if ( imageView == profileSign )
    {
        feedSign.hidden = true
        exploreSign.hidden = true
        cameraSign.hidden = true
        chatSign.hidden = true
        profileSign.hidden = false
        viewControllerIndex = 4
    }

   displayViewController(atIndex: viewControllerIndex)
}

Each tab in bar has it's own action and each green line at bottom has it's outlet :

    @IBAction func feedControllerSelected()
{
    setUpTabBar(forSelectedActionSignContainer: feedSign)
}

@IBAction func exploreControllerSelected()
{
    setUpTabBar(forSelectedActionSignContainer: exploreSign)
}

@IBAction func cameraControllerSelected()
{
    setUpTabBar(forSelectedActionSignContainer: cameraSign)
}

@IBAction func chatControllerSelected()
{
    setUpTabBar(forSelectedActionSignContainer: chatSign)
}


@IBAction func profileControllerSelected()
{
    setUpTabBar(forSelectedActionSignContainer: profileSign)
}

private func initialSetUp()
{
    setUpTabBar(forSelectedActionSignContainer: feedSign)
}

And in viewDidAppear of tabbar controller i make initial configuration by calling setUpTabBar(forSelectedActionSignContainer: feedSign). So child controllers don't manage anything, line in the original UITabbarController

EDIT 2

All this happens on device, when i adding UITableView to child view controller. Without it - everything works. It seems like some exception rises on device, but it doesn't propagate to xcode via wire somehow.


Solution

  • And after 4 hours of investigation i found the following :

    1. My issue reproduces only if start view controller contains table view
    2. It doesn't reproduce, if table view contains 0 rows
    3. It still reproduces with default UITabbarController
    4. In my UITableViewCell, surely a custom one, i've got horizontal scroller - HorizontalTableView form GitHub.
    5. After removing it, everything works like a charm.

    SUMMARY

    1. This issue definitely causes by some internal UIKit exception, that doesn't raise it properly
    2. It reproduces only on real devices. In simulator there's no such problem
    3. How could Apple do this in UIKit?! Hate em all! Cook, apple, xcode!

    Thanks everyone!