views:

1342

answers:

3

Hello, in my app i have an UITabBarController with UINavigationControllers initialized like this

UINavigationController *newsNavigationController = [[UINavigationController alloc] initWithRootViewController: newsViewControler];

newsViewController is an UIViewController. When i press the button in the tabbar to show the navigation item with the newsViewController the title in the navigation bar is set ok. in the newsViewController i have a method setup that i call after init. In the setup method i set the title like this [[self navigationItem] setTitle:[category_c title]];

The problem comes now, in my newsViewController i have a tableView, when i touch a cell i want to push a UIViewController with the selected news and in the navigation bar to show the title.

In the UIViewController i have the same setup method in which i setup the title like above. The problem is that is not shown. The navigation item is not null because i can call self.navigationItem.hidesBackButton = YES; and it hides the backbutton every time but the title isn't shown.

I create and push the news UIViewController like this when a cell is touched

if(newsViewController == nil){
        newsViewController = [[NewsViewController alloc] init];
        [newsViewController setup];
    }
    [self.navigationController pushViewController: newsViewController animated:YES];

The setup method in the newsViewController looks like this:

- (void) setup {
    self.navigationItem.hidesBackButton = YES;
    [self.navigationItem setTitle:@"my view"];
}

in the newsViewController i have viewDidLoad and tried to set the title there but with no success.

  • (void)viewDidLoad { self.navigationItem.title = @"Test"; [super viewDidLoad]; }

if after [self.navigationController pushViewController: newsViewController animated:YES]; i write [[self.navigationController.viewControllers objectAtIndex:0] setTitle:@"myTitle"]; the UIViewController that contains the UITableView gets the title myTitle instead of the newsViewController that i pushed when i touched the cell.

any pointers? i can't understand why the title is not set correctly.

EDIT2: After reading a little more and going through my code with the debugger step by step and comparing the rootviewcontrollers with the childViewControllers i've observed that in the viewDidLoad method of the childViewController after setting self.title = @"title" the navigationItem is created so it's not the nil situation. In the debugger when i expand the _navigationItem variable the field _navigationBar is nil after leaving viewDidLoad, in the rootViewControllers the navigationBar is NOT NULL and the title is there. I read that if the navigationBar is null the title will not show up. In the image is what i've seen in the debuger. alt text now i'm searching in this direction.

EDIT1: below is the code for the parentViewController, firstChildViewController and second ChildViewController. the parentViewController is viewed(the title is OK). I press a button on the navigationBar that calls bearbeitenAction -> the first child is pushed(title is not showed). On the navigation bar of the firstChildViewController i have a button that when is pressed pushes a new ViewController on the stack(secondChildViewController). The title of the second ChildViewController is not ok. When i press Back the title of the firstChildViewController is showed Ok.

parentViewController:

    //MARK: -
    //MARK: Initialization methods
    - (void) setup {
        dataManipulator = [[DataManipulation alloc] init];
        dataManipulator.delegate = self;

        [self.tabBarItem initWithTitle:[NSString stringWithFormat:@"%@",[category_c title]] image:[UIImage newImageFromResource:[category_c icon]] tag:0];

        searchResults = nil;
        companyDetailsPushed = NO;
    }

    //MARK: -
    //MARK: ViewControllerMethods
    // Implement loadView to create a view hierarchy programmatically, without using a nib.
    - (void) loadView {
        NSLog(@"WatchlistViewController: loadView");

        UIView *mainView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] applicationFrame].size.width, [[UIScreen mainScreen] applicationFrame].size.height)] autorelease];
        [mainView setBackgroundColor:[UIColor whiteColor]];
        mainView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        mainView.contentMode = UIViewContentModeScaleToFill;
        [mainView setAutoresizesSubviews:YES];

            companiesTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 44, [[UIScreen mainScreen] applicationFrame].size.width, 322)];
        companiesTable.delegate = self;
        companiesTable.dataSource = self;
        [mainView addSubview:companiesTable];
        [companiesTable release];

            self.view = mainView;
    }

    - (void)viewDidLoad {
        [super viewDidLoad];
        if(![[category_c subtitle] isEqualToString:@""]) {
            self.title = [category_c subtitle];
        }
        else {
            self.title = [category_c title];
        }
    }

    - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

        if(companyDetailsViewController == nil) {
            companyDetailsViewController = [[CompanyDetailsScrollViewController alloc] init];
            [companyDetailsViewController setup];
        }

        [watchlistDoneBtn setHidden:TRUE];
        companyDetailsPushed = YES;

        if(viewMode == SearchViewMode)
            [companyDetailsViewController setCompany:[searchResults objectAtIndex:indexPath.row]];
        else if(viewMode == WatchlistViewMode)
            [companyDetailsViewController setCompany:[[[Financial_deAppDelegate sharedAppDelegate] watchlistCompanies] objectAtIndex:indexPath.row]];

        [[self navigationController] pushViewController:companyDetailsViewController animated:YES];
    }

- (void) bearbeitenAction:(UIButton *) sender {
    NSLog(@"Berbeiten btn was pressed");
    if(berbeitenViewController == nil){
        berbeitenViewController = [[BerbeitenViewController alloc] init];
        [berbeitenViewController setup];
    }
    [self.navigationController pushViewController:berbeitenViewController animated:YES];
}

firstChildViewController = berbeitenViewController in the code:

- (void) setup {
    self.navigationItem.hidesBackButton = YES;
}

// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
    NSLog(@"BerbeitenViewController: loadView");

    UIView *mainView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] applicationFrame].size.width, [[UIScreen mainScreen] applicationFrame].size.height)] autorelease];
    [mainView setBackgroundColor:[UIColor darkGrayColor]];
    mainView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    mainView.contentMode = UIViewContentModeScaleToFill;
    [mainView setAutoresizesSubviews:YES];

    berbeitenBackBtn = [[UIButton alloc] initWithFrame:CGRectMake(5, 23, 69, 36)];
    [berbeitenBackBtn setBackgroundImage:[UIImage newImageFromResource:@"back_btn.png"] forState:UIControlStateNormal];
    [berbeitenBackBtn addTarget:self action:@selector(popViewController:) forControlEvents:UIControlEventTouchUpInside];
    [berbeitenBackBtn setEnabled:TRUE];
    [self.navigationController.view addSubview:berbeitenBackBtn];
    [berbeitenBackBtn release];

    berbeitenAddBtn = [[UIButton alloc] initWithFrame:CGRectMake(260, 23, 55, 36)];
    [berbeitenAddBtn setBackgroundImage:[UIImage newImageFromResource:@"bearbeiten_add_btn.png"] forState:UIControlStateNormal];
    [berbeitenAddBtn addTarget:self action:@selector(addCompany:) forControlEvents:UIControlEventTouchUpInside];
    [berbeitenAddBtn setEnabled:TRUE];
    [self.navigationController.view addSubview:berbeitenAddBtn];
    [berbeitenAddBtn release];

    companiesTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] applicationFrame].size.width, 366)];
    companiesTable.delegate = self;
    companiesTable.dataSource = self;
    [mainView addSubview:companiesTable];
    [companiesTable release];

    self.view = mainView;
}

- (void)viewDidLoad {
    NSLog(@"BerbeitenViewController viewDidLoad");
    [super viewDidLoad];
    self.title = @"Edit watchlist";
}

//MARK: Buttons actions

- (void) popViewController:(UIButton *) sender {
    NSLog(@"Pop BerbeitenViewController");
    [self.navigationController popViewControllerAnimated:YES];
}

- (void) addCompany:(UIButton *) sender {
    NSLog(@"Berbeiten addCompany btn pushed");
    if(searchViewController == nil){
        searchViewController = [[SearchViewController alloc] init];
        [searchViewController setup];
    }
    [self.navigationController pushViewController:searchViewController animated:YES];
}

secondChildViewController = searchViewController in code

- (void) setup {
    self.navigationItem.hidesBackButton = YES;
}

// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
    NSLog(@"BerbeitenViewController: loadView");

    UIView *mainView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] applicationFrame].size.width, [[UIScreen mainScreen] applicationFrame].size.height)] autorelease];
    [mainView setBackgroundColor:[UIColor darkGrayColor]];
    mainView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    mainView.contentMode = UIViewContentModeScaleToFill;
    [mainView setAutoresizesSubviews:YES];

    searchViewBackBtn = [[UIButton alloc] initWithFrame:CGRectMake(5, 23, 69, 36)];
    [searchViewBackBtn setBackgroundImage:[UIImage newImageFromResource:@"back_btn.png"] forState:UIControlStateNormal];
    [searchViewBackBtn addTarget:self action:@selector(popViewController:) forControlEvents:UIControlEventTouchUpInside];
    [searchViewBackBtn setEnabled:TRUE];
    [self.navigationController.view addSubview:searchViewBackBtn];
    [searchViewBackBtn release];

    self.view = mainView;
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"Edit Watchlist";
}
+1  A: 

EDIT #2

I looked through your code and everything seems okay. The only thing that looks out of place to me is that you are adding a subview to the navigation controller instead of using the child controller's navigationItem. I have never seen it done this way. Each ViewController has a UINavigationItem property that represents the view controller when it is pushed onto a navigation bar. Just read through the Overview of the documentation for some background.

That NavigationItem has a title, left-button and right-button that you can set... I would try setting your buttons to those properties because by adding subviews to the navigation controller it could be doing something funky with the title... Again, I have never seen it done the way you are doing it so I 'm not really sure if it is right or wrong. The only changes you will have to make is changing the buttons to the UIBarButtonItem class. Give it a try.

Original

The root view controller is at index 0 in the array... so if you doing this:

[[self.navigationController.viewControllers objectAtIndex:0] setTitle:@"myTitle"]

it will always set the root's title. Try to do it at:

objectAtIndex:([self.navigationController.viewControllers count] - 1)

It might even be easier to do this sort of setup in the child controller's viewWillAppear method... that way you don't have to search through the navigation controller's children for the correct view controller.

hope this helps

EDIT You could try ONLY setting the title in the init method:

-(id)init {
    if (self = [super init]) {
        self.title = @"My Title";
    }
    return self;
}

This way, you are allowing the object's init method to be in charge of initializing the object's values (which is a good thing).

Ryan Ferretti
hello Ryan, i tried to put [[self.navigationController.viewControllers objectAtIndex:([self.navigationController.viewControllers count] - 1)] setTitle:@"myTitle"]; but the effect was the same. Also in the child viewController i set [self setTitle:@"myView"] and the result is the same :( no title.
SorinA.
Hmmm... I don't see much else based on the code you have posted. Have you tried stepping through your code with the debugger? I know that I first had problems with this stuff and stepping through it helped a lot. Are you using 2 different nibs for your views or are they in the same nib? There isn't much to setting the title, so it is probably something really small.
Ryan Ferretti
i'm doing everything by code. if i set [self.navigationItem setTitle:@"Edit watchlist"]; and i push from the childViewController another view, when i push the "back" button to go to the childViewController the title is set! when i push "back" again to go to the tableView and then select another cell the title is not shown...
SorinA.
It seems like you are setting the title on the wrong controller. If you are calling setTitle on self and then pushing on a child-view... then the title will be set on the parent. What I would suggest is removing all setTitle calls from places where you are pushing on child-views. That way, you only have 1 set title per controller. You can be sure that it is being set if you create a custom init method where you call self.title = @"myTitle"
Ryan Ferretti
check out the edit to my answer
Ryan Ferretti
Hello Ryan, i tried what you said but it doesn't work..i'm setting the title in the child view controller that i am pushing in the viewDidLoad method. I have no idea why the title isn't showing.
SorinA.
Hello Ryan, i added some code from the parent, first child and second child view controllers. Maybe you can point out something that i'm doing wrong. Thank you!
SorinA.
I updated my answer with the part about the navigationItem... Give that a try.
Ryan Ferretti
hello Ryan i tried what you suggested. In my childViewController in viewDidLoad i set my title like [self.navigationItem setTitle:@"myTitle"] but the effect is the same. i modified the buttons also, i added them to the navigationItem left and right buttons but the result is the same. The result is the same. It's pretty weird what is happening.. i can't understand why the title isn't shown. Thank you!
SorinA.
glad you found your answer... if my answers were helpful to you, give me an up-vote :)
Ryan Ferretti
+1  A: 

You should move the setup code to the viewDidLoad method instead. The viewDidLoad is called when the navigation item has already been setup for you.

To set the title, simply use self.title = @"my view"; - you should not set the title directly on the navigationItem.

St3fan
hello St3fan, i've done what you suggested. in the child UIViewController in the viewDidload method i set self.title = @"my view" but the title doesn;t apear the first time. if u push another view and press the back button then the "my view" title will appear...i really don't know why this is happening.
SorinA.
hi St3fan, i added some code from the parent and children view controllers in the edit. maybe i'll see something wrong with what i did. Thank you!
SorinA.
A: 

the source of the problem was the custom background image for the navigationBar that i added using the method found at this address http://sebastiancelis.com/ . Basically what happened was and i quote from the author:

By using a category, we could easily add our own setBackgroundImage: method and call it whenever we create a UINavigationBar or UINavigationController. This method would just add a UIImageView as a subview to the navigation bar and then send that subview to the back of its superview.

However, if you try this you will quickly see that it only kind of works. The UIImageView is definitely visible and even initially at the correct z-index. However, once you push or pop a view controller onto the navigation controller's stack, you will see that the background image is no longer in the background. Instead, it blocks out the title and navigation bar buttons. This is definitely not what we want.

when i found this solution for changing the background of the navigationBar i was pretty sure that i got it right but it seems i didn't..

thank you again for your time!

SorinA.