0

I'm attempting to use a UINavigationController that utilizes a custom subclass of UINavigationBar. However, I'm running into a problem with initWithFrame. When initWithFrame is called, I print out the dimensions and it shows a 0.0 width and 0.0 height. But, when I print out the same frame in -(void) layoutSubviews inside of the UINavigationBar subclass, the frame is correctly set. Why is initWithFrame receiving a zero-sized frame, and what can I do to fix this? It doesn't sound correct to be manually calling initWithFrame or anything like that, since UINavigationController should take care of that. Here is the relevant code:

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    UINavigationController *navController = [[UINavigationController alloc] initWithNavigationBarClass:[CustomNavigationBar class] toolbarClass:nil];
    CoolViewController *vc = [[CoolViewController alloc] init];
    [navController pushViewController:vc animated:YES];
    self.window.rootViewController = navController;

    [self.window makeKeyAndVisible];

    return YES;
}

CustomNavigationBar.m

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        NSLog(@"initWithFrame with frame: %f, %f", frame.size.width, frame.size.height); // This prints "initWithFrame with frame: 0, 0"
    }

    return self;
}

Thank you!

J Kagney
  • 239
  • 1
  • 4
  • 9
  • What problem does it cause you? – Wain Jun 14 '13 at 22:20
  • Not a problem perse, but I'm cautiously curious why initWithFrame, which is getting called ostensibly by UINavigationController, is getting fed a zero x zero frame. Is it a fact that I should initialize the UINavigationBar subclass in -(void) layoutSubviews or am I not setting something properly, causing the frame to be wrong in initWithFrame? – J Kagney Jun 14 '13 at 22:38

1 Answers1

1

I believe the navigation controller doesn't actually set the frame size to a specified value. Instead, it asks the navigation bar for its sizeThatFits: and uses that. By definition, that can't be done and passed to initWithFrame:. So, you want to use a combination of sizeThatFits:, setFrame: and layoutSubviews to add, size and reset your navigation bar content.

Wain
  • 118,658
  • 15
  • 128
  • 151
  • Thanks for the reply, I had no idea that sizeThatFits even exists. I'll try implementing this solution. – J Kagney Jun 15 '13 at 15:51
  • I implemented it this way and it seems to be working perfectly. Just to makes sure though, I'm supposed to allocate and initialize the custom parts of my nav bar in initWithFrame, but save the frame setting for layoutSubviews? I'm assuming when you said setFrame: is used, you meant its used inside of layoutSubviews to set the subviews of the nav bar's frames? – J Kagney Jun 15 '13 at 16:33
  • SetFrame could be used to trigger some image modification if you needed it or to force relayout. But you don't need to use it. – Wain Jun 15 '13 at 17:30