0

At the moment I am building an iPhone application which has several purposes. One of the purposes a dashboard for known users (need to login). Inside the UINavigationController I use a UIView with a simple button. On the button press I go to either the dashboard page of the login page using a push segue. This works exactly like I intend to do.

But when I am on the login page, after filling the right login credentials, and press the login button. I can go to the dashboard page, but when I press the back button, I'll enter the login page again. Which is not what I want. So I searched for ways to delete the page of the viewControllers array in self.navigationController.viewControllers which should do the job. But this is where I am stuck...

What is the right way to remove a UIViewController from the stack? I tried several things like:

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSMutableArray *viewControllersInStack = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];

    if([viewControllersInStack count] > 3)
    {
        [viewControllersInStack removeObjectAtIndex:1];
    }

    //self.navigationController.viewControllers = [[NSArray alloc] initWithArray:viewControllersInStack];
    //[self.navigationController setViewControllers:[[NSArray alloc] initWithArray:viewControllersInStack] animated:YES];
}

Putting this in the dashboard class gave me the most success. When pressing the back button in the UINavigationBar, it'll enter the first page but without the UINavigationBar item, but I can press the back button one more time which shouldn't be possible. If I press it, it'll show an empty page with the UINavigationBar item. I have this item for a link to a 'more information' page.

In the login class I tried several things when pressing the login button, some of them are:

//[self.navigationController popViewControllerAnimated:NO];
//[self performSegueWithIdentifier:@"loginToDashboard" sender:self];

//DashBoardViewController *dashboard = [DashBoardViewController alloc];
//[self.navigationController popToViewController:(UIViewController *)dashboard animated:YES];

[self.navigationController popToRootViewControllerAnimated:NO];
[self performSegueWithIdentifier:@"homeToDashboard" sender:self];

The loginToDashboard segue is the one from the login page to the dashboard and the homeToDashboard is from the root to the dashboard. But all of these will give me an exception like:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver () has no segue with identifier 'homeToDashboard''

or

Terminating app due to uncaught exception 'NSGenericException', reason: 'Could not find a navigation controller for segue 'loginToDashboard'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.

Update:

I have the following code:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.navigationItem.hidesBackButton = YES;

    //UIBarButtonItem* button = self.navigationItem.backBarButtonItem;

    //[button setTitle:@"Test"];
    //[button setAction:@selector(returnToHome)];

    //self.navigationItem.backBarButtonItem = button;

    UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc] initWithTitle:@"< Home" style:UIBarButtonItemStyleBordered target:self action:@selector(returnToHome)];
    self.navigationItem.leftBarButtonItem = backBarButton;
}

- (void)returnToHome
{
    [self.navigationController popToRootViewControllerAnimated:YES];
}

Now the code works like a charm! But... How can I get the same arrow ('<', less-than sign) as in the default Navigation Controlers.

Sietse
  • 623
  • 1
  • 8
  • 23
  • Check my answer in http://stackoverflow.com/questions/22301647/push-to-viewcontroller-without-back-button/22301770#22301770 – user2071152 Mar 10 '14 at 13:47
  • This works, but is not exactly what I had in mind. The back button must be replaced with another item (need to check if I can have the same look and feel, if so, this is the best way for now). Why can't I adjust the action for the original back button like: [self.navigationItem.backBarButtonItem setAction:@selector(returnToHome)]; – Sietse Mar 10 '14 at 15:24
  • Another problem is the title for the home page is gone, even if I set the self.navigationController.navigationBar.topItem.title to @"something" it won't accept it. – Sietse Mar 10 '14 at 15:31
  • Could you please try to self.title = @"screen title" and check. – user2071152 Mar 10 '14 at 18:47
  • `- (void)viewDidAppear:(BOOL)animated { self.title = @"Test"; }` Doesn't do the job... – Sietse Mar 11 '14 at 07:40
  • Can you please post the code which you are using. – user2071152 Mar 11 '14 at 10:20
  • I have updated my question which include some more code. The title is already working. I tried to delete the title and only get the arrow to the left, but since that doesn't work, I leave the name of the parent page in there. Now the only problem still remaining is the arrow in the back button. Since it is a custom back button, it doesn't include the arrow automatically, is there a way to do that? If so, can you create an answer so I can accept it? – Sietse Mar 11 '14 at 13:25

2 Answers2

1

No you can't add the arrow, in case of Custom Back button you will either have an custom image or Custom Text set in Back button.

The Custom Back button with an image can be created using the method. The method CustomBackButton has to be included in viewWillAppear() method of a UIViewController.

- (void)CustomBackButton
{
    UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 34, 26)];
    [backButton setBackgroundImage:[UIImage imageNamed:@"back_arrow.png"] 
                                   forState:UIControlStateNormal];
    UIBarButtonItem *barBackButtonItem = [[UIBarButtonItem alloc] 
                                         initWithCustomView:backButton];
    [backButton addTarget:self action:@selector(popCurrentViewController) 
    forControlEvents:UIControlEventTouchUpInside];
    self.navigationItem.leftBarButtonItem = barBackButtonItem;
    self.navigationItem.hidesBackButton = YES;
}

- (void)popCurrentViewController
{
    [self.navigationController popViewControllerAnimated:YES];
}

Please find some links where its explained to created Custom Back buttons.

http://www.appcoda.com/customize-navigation-status-bar-ios-7/ http://www.dev-smarter.com/uinavigationcontroller-with-a-custom-back-button-image/

Hope this helps.

user2071152
  • 1,161
  • 1
  • 11
  • 25
0

If you already know the class of the view controller you want to find in your stack, you could try this:

for (UIViewController *controller in [self.navigationController viewControllers])
{
    if ([controller isKindOfClass:[YourFirstViewController class]])
    {
        [self.navigationController popToViewController:controller animated:YES];
        break;
    }
}
Sti
  • 8,275
  • 9
  • 62
  • 124
  • I can pop to the view controller, but the view controller is not yet in the stack. The pages in the stack are Home -> Login and after the login they are Home -> Login -> Dashboard, but I want them to become Home -> Dashboard if this is possible. – Sietse Mar 10 '14 at 14:56
  • @Sietse Ah, I see. Take a look at this. http://stackoverflow.com/a/15839298/1203228 – Sti Mar 12 '14 at 18:48