PersonViewController in TabBarController
Asked Answered
H

2

11

I have a UITabBarController with three tabs. When a certain one is pressed, I'd like the user to immediately see a person view controller (an instance of the ABPersonViewController class).

I don't want to just use the presentViewController() method with a person view controller as a parameter because this results in a lag, when the user can see the underlying view controller from which it's presented.

I also can't make the view controller inherit from ABPersonViewController, because it's set by Apple so that it can't be subclassed. Is there a way I can accomplish this?

Thanks to JAL's answer:

func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {

    let navViewController = viewController as! UINavigationController

    // First, check to see if the view controller is the one you want to override
    if let myViewController = navViewController.viewControllers[0] as? ThirdViewController {

        let abpvc = ABPersonViewController()
        abpvc.personViewDelegate = self
        self.navigationController?.pushViewController(abpvc, animated: true)
        return false

    }

    return true
}
Hemicycle answered 14/8, 2015 at 2:0 Comment(1)
Please don't copy/include an answer into your question. If an answer helped you you can upvote and or accept it. But an answer doesn't belong into the question.Abate
A
1

Answer

The essential idea is to subclass UITabBarController and put a UIButton on the tab bar, cover up the original tab area and add an action to that button, which will trigger relevant function calls.

So that the tap event actually never being passed to the tabBarController, but only to the button. So that the user will never "see the underlying view controller".

Sample Code

Sample Swift 1.2 code that add a button to the center of UITabBarController

func AddSampleButton(){
    let SampleButton = UIButton()
    SampleButton.setTranslatesAutoresizingMaskIntoConstraints(false)
    SampleButton.setBackgroundImage(addImage, forState: UIControlState.Normal)

    SampleButton.addConstraint(NSLayoutConstraint(item: addButton, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.view.frame.size.width/5))

    SampleButton.addConstraint(NSLayoutConstraint(item: addButton, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 50))

    self.view.addSubview(addButton)

    self.view.addConstraint(NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: addButton, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0))

    self.view.addConstraint(NSLayoutConstraint(item: self.view, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: addButton, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0))

    SampleButton.enabled = true
    SampleButton.addTarget(self, action: "SampleAction", forControlEvents: UIControlEvents.TouchUpInside)
}

func SampleAction() {
    let abpvc = ABPersonViewController()
    abpvc.personViewDelegate = self
    self.navigationController?.pushViewController(abpvc, animated: true)
}

Reference:

http://idevrecipes.com/2010/12/16/raised-center-tab-bar-button/

Notice

If you didn't see the button, be mindful of the lifecycle of UIViewContoller, cause that maybe the source of your error.

Allo answered 24/8, 2015 at 8:14 Comment(0)
T
-1

Use the UITabBarDelegate method shouldSelectViewController:

func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {

    // First, check to see if the view controller is the one you want to override 
    if let myViewController = viewController as? ViewControllerToOverride {
        // do something here, present a new view controller, etc.
        return false // then return false to prevent the tab from switching

}

To select the tab bar item (if you're using an image), change the UITabBarItem's image or selectedImage. Because you're returning false when you select the tab, you will probably need to change the image property rather than the selectedImage.

self.tabBar.items?.first?.image = UIImage(...)
Tasha answered 18/8, 2015 at 1:43 Comment(9)
A breakpoint in the first line of this method is never reached, suggesting it's not actually called when a tab bar item is pressed and a new vc is presented.Hemicycle
Did you set the tab bar delegate property to the class where you call that method?Tasha
Are we talking about UITabBarDelegate or UITabBarController delegate? You said UITabBarDelegate, but it appears from the documentation that only UITabBarControllerDelegate has that method?Hemicycle
Sure you can, just unwrap the navigation controller's first view controller. That should be the view controller you want.Tasha
Is there any way to modify this so that the tab bar item that we're intercepting is highlighted when pressed on?Hemicycle
If my answer helped you, please mark it as accpeted. If you have any additional questions, it may be best to ask a new question.Tasha
This isn't an additional question—it's a key part of what I'm looking for. A solution that swaps out one problem for another isn't a solution. Your answer was very helpful, but incomplete.Hemicycle
It's really not clear what you want. You're selecting a tab, overriding the selection, and then want to set the tab as selected? Nevertheless I have added a way to select the tab to my answer.Tasha
VC does not have a member named 'tabBar', and anyway, I need to change the icon of the VC which is being selected not the present one, and I'd like to set it to whatever the selected image for that tab bar item is, not a custom UIImage.Hemicycle

© 2022 - 2024 — McMap. All rights reserved.