Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the title UILabel of a UIViewController

Tags:

ios

uilabel

ios7

The following does not work

UILabel *titleLabel = (UILabel *)self.navigationController.navigationItem.titleView;

OR

UILabel *titleLabel = (UILabel *)self.navigationItem.titleView;

Both return nil.

Yes, the title in question is in the navigation bar. The objective is simple: I want the UILabel. Can that be done?

UPDATE

One of the reasons I needed the UILabel is so that I could grab its width after I fill it with text, which would essentially tell me the max width of the label (basically a device agnostic way of measuring: whether iPad, iPhone, etc).

like image 380
learner Avatar asked Feb 12 '23 07:02

learner


2 Answers

The short answer: You can't. UINavigationBar 's internals handle the display of a UIViewController's title. The titleView property of UINavigationItem is used for other purposes.

The long answer

Look at UINavigationBar.h and get a rough understanding of how they both work together. - You'll quickly see why the titleView has nothing to do with a viewController's title.

UINavigationItem is the dataSource for a UINavigationBar. It holds the barButtonItems, the title and the titleView for each UIViewController. Look at the UIViewController (UINavigationControllerItem) category defined in UINavigationController.h there is a good explanation in the comments there.

The UINavigationBar on the other hand is 'simply' displaying the content of UINavigationItems. When you push a viewController onto the stack of a navigationController, the navigationController implicitly calls UINavigationBar: pushNavigationItem:animated: on its navigationBar, sending the UINavigationItem of the viewController you are pushing.

I see you have the same misconception that i had when i started digging into UINavigationControllers:

The fact that you can write things like UILabel *titleLabel = (UILabel *)self.navigationController.navigationItem.titleView; without any warning is very misleading

UINavigationController does not have a UINavigationItem. It will never have. This is because a navigationController will never be contained inside another navigationController. (If you try to build this containment in IB it will give you a warning i think !?) The reason you can call self.navigationController.navigationItem is that the category i mentioned above is giving EVERY UIViewController a UINavigationItem property. UINavigationController in turn IS a UIViewController and thus receives the property from the category within its own implementation. - That's very confusing!

I assume you want to grab a reference to the titleLabel (even though you can't !), because you want to set the font or the textcolor of the title. If so, you can do these things through UINavigationBar: setTitleTextAttributes:.

If you want to use a complete custom titleView, you are better off creating a UILabel and assigning it to the titleView property of the UINavigationItem

like image 128
CodingMeSwiftly Avatar answered Feb 22 '23 12:02

CodingMeSwiftly


this works for me:

- (UILabel *)getNavBarTitleLabel
{
    UINavigationBar *navBar = self.navigationController.navigationBar;
    if (!navBar) { return nil; }

    for (UIView *subview in navBar.subviews) {
        for (UIView *subSubview in subview.subviews) {
            if ([subSubview isMemberOfClass:[UILabel class]])
            {
                // consider adding more checks to verify that this UILabel is indeed the title label before returning it
                // for example, if you know what the text should be you can compare the strings
                return (UILabel*)subSubview;
            }
        }
    }
    return nil;
}
like image 31
banana1 Avatar answered Feb 22 '23 12:02

banana1