简体   繁体   中英

UINavigationItem TitleView disappears

I am trying to create a custom titleView for a navigation bar. I am able to set the titleView in the root view controller that is embedded in a navigation controller.

When I push the second view controller onto the stack and try to set the titleView for this view controller it does not work. The titleView quickly appears and disappears. When I go back to the previous view controller this titleView quickly appears and disappears now also.

Does anyone know why this is happening or how to set the titleView correctly without flashing and disappearing?

class FirstViewController: UIViewController {

    var titleView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        addTitleView()
    }

    func addTitleView() {
        titleView = UIView(frame: CGRect(x: 0, y: 0, width: 150, height: 44))

        let companyLabel = UILabel(frame: CGRect(x: 0, y: 3, width: 150, height: 11))
        companyLabel.text = "CPS Dashboard"
        companyLabel.textColor = UIColor.grayColor()
        companyLabel.textAlignment = .Center
        companyLabel.font = UIFont.systemFontOfSize(9)
        titleView.addSubview(companyLabel)

        let titleLabel = UILabel(frame: CGRect(x: 0, y: 16, width: 150, height: 18))
        titleLabel.text = "Dashboard"
        titleLabel.textColor = UIColor.blackColor()
        titleLabel.textAlignment = .Center
        titleLabel.font = UIFont.systemFontOfSize(15)
        titleView.addSubview(titleLabel)

        navigationItem.titleView = titleView
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "Show" {
            let controller = segue.destinationViewController as! SecondViewController
            controller.titleView = titleView
        }
    }
}

The second viewcontroller:

class SecondViewController: UIViewController {

    var titleView: UIView?

    override func viewDidLoad() {
        super.viewDidLoad()

        if let titleView = titleView {
            navigationItem.titleView = titleView
        }
    }
}

I found a solution. I copied addTitleView() method from FirstViewController into SecondViewController, and called both of them in viewDidLoad(). This worked exactly as I wanted it to. For some reason it was not working to pass the titleView forward as a property and assigning it to navigationItem.titleView.

class FirstViewController: UIViewController {

    var titleView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        addTitleView()
    }

    func addTitleView() {
        titleView = UIView(frame: CGRect(x: 0, y: 0, width: 150, height: 44))

        let companyLabel = UILabel(frame: CGRect(x: 0, y: 3, width: 150, height: 11))
        companyLabel.text = "CPS Dashboard"
        companyLabel.textColor = UIColor.grayColor()
        companyLabel.textAlignment = .Center
        companyLabel.font = UIFont.systemFontOfSize(9)
        titleView.addSubview(companyLabel)

        let titleLabel = UILabel(frame: CGRect(x: 0, y: 16, width: 150, height: 18))
        titleLabel.text = "Dashboard"
        titleLabel.textColor = UIColor.blackColor()
        titleLabel.textAlignment = .Center
        titleLabel.font = UIFont.systemFontOfSize(15)
        titleView.addSubview(titleLabel)

        navigationItem.titleView = titleView
    }
}

The second viewcontroller:

class SecondViewController: UIViewController {

    var titleView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        addTitleView()
    }

    func addTitleView() {
        titleView = UIView(frame: CGRect(x: 0, y: 0, width: 150, height: 44))

        let companyLabel = UILabel(frame: CGRect(x: 0, y: 3, width: 150, height: 11))
        companyLabel.text = "CPS Dashboard"
        companyLabel.textColor = UIColor.grayColor()
        companyLabel.textAlignment = .Center
        companyLabel.font = UIFont.systemFontOfSize(9)
        titleView.addSubview(companyLabel)

        let titleLabel = UILabel(frame: CGRect(x: 0, y: 16, width: 150, height: 18))
        titleLabel.text = "Dashboard"
        titleLabel.textColor = UIColor.blackColor()
        titleLabel.textAlignment = .Center
        titleLabel.font = UIFont.systemFontOfSize(15)
        titleView.addSubview(titleLabel)

        navigationItem.titleView = titleView
    }
}

My solution is simple, and it works:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    if let tv = navigationItem.titleView {
        print("transform", tv.transform)) // is always identity
        let bounds = tv.bounds
        print("bounds", bounds) // its origin may not be zero.
        tv.bounds = CGRect(origin: .zero, size: bounds.size)
        print("new bounds", tv.bounds)
    }
}

Using Xcode's view debugger, you will find that titleView.bounds.origin is not zero.
How to let it happen again , two steps: 1. UIViewController A and B; A has custom navigationItem.titleView , B hides navigationBar in its viewWillAppear() ; when B poped, A.viewWillAppear() setNavigationBar(hidden: false, animated: true) 2. user-driven popViewController is canceled by lifting your hand.
Then you will found, A's navigationBar is blank.

I was having this same issue, but none of the above solutions fixed it for me. My issue was that I was setting translatesAutoresizingMaskIntoConstraints to false . I imagine this caused the appearing/disappearing because it needs to be set to true in order to constrain the view internally to the navigation bar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM