Navigation bar back button change functionality - ios

I have 3 view controllers: A, B and C. A is initial and it has 2 buttons: one is redirecting to B, and second one to C. When B is pushed, and button within B pressed user is redirected to C. Now on navigation bar within C, when I press back button I want to be redirected to A always, and never to B. Is that possible?
This is base functionality I want to achieve:
a)
A->B->C C back to A
b)
A->C C back to A

for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:[A class]])
{
[self.navigationController popToViewController:controller
animated:YES];
break;
}
}

you can achieve this with presentview controller as modal view.first from a if first button is pressed present b view.if secnd button is pressed present c view and in c view controller put back button and add delegates and implement the delegate in a view controller.and you will have to dismiss one view after the other in a view controller.

The only way is replacing the back button by a custom button.

After reading what you said I think you meant implementing custom actions for each button.The way I would do it(In Swift) is this:
#IBAction func pressButton(sender : UIButton){
var SecondView :ViewController2
SecondView = self.storyboard?.instantiateViewControllerWithIdentifier("SecondView") as ViewController2
self.presentViewController(SecondView, animated: true, completion:nil)
self.viewWillDisappear(true)
}
This method I have used a lot and I know there is another way using segues but you still use #IBActions.You just create a new segue(identifier) and in the prepareforSegue method you say what happens when that segue is triggered

Related

iOS Navigation Back Button

I’m having a scenario, 

I had 3 controllers, lets assume A,B and C. When app launches I’m transitioning from A to C using segue. Later, in C by using a button I’m moving to B using segue again. So, now I’m in B when I click “Back” it is transitioning to C, but it has to move to A.


How is this possible, any hint/idea?
Put this code in B controller's back button.
for viewcontroller in self.navigationController!.viewControllers as Array {
if viewcontroller.isKindOfClass(HomeVC) { // change HomeVC to your viewcontroller in which you want to back.
self.navigationController?.popToViewController(viewcontroller as! UIViewController, animated: true)
break
}
}
OR
If Class A is your RootView controller
self.navigationController?.popToRootViewControllerAnimated(true)
If your Class A viewController is root, you can set this code on back button:
self.navigationController?.popToRootViewControllerAnimated(true)

How to perform segue inside unwind function

I have 3 MVCs and name them A, B, C here.
A is the main MVC with a button "Menu" connected to B with popover segue.
A also connected to C with a manual show segue.
B is a popover MVC with a button "Detail" connected to A with unwind segue.
C is the detail MVC with detail info.
Inside the unwind function of A. I call performSegueWithIdentifier to show C.
Expected behavior is
Click "Detail" button in B
B disappear and A show up
C show up
But running the app I got.
Click "Detail" button in B
B disappear and A show up
C show up
C disappear and A show up
C show up and disappear suddenly which is not what I want.
Some additional info
Popover B is needed for more buttons.
A is embeded in a UINavigationController. Connecting A -> C rather than B -> C, for a Back button on top of C.
Seems unwind function is not the correct place to call performSegueWithIdentifier.
UIKit will pop view controller after calling the unwind function.
Thus push new view controller inside unwind function will pop quickly.
The solution is to delay performSegueWithIdentifier.
Solution 1: NOT WORKING FINE
Adding an bool instance and inside viewDidAppear use this instance to determine if we perform segue.
Won't work if B controller is a popover. After B popover disappear, viewDidAppear is not called for A controller.
Solution 2: WORKING
Push performSegueWithIdentifier into main queue.
#IBAction func unwind(segue : UIStoryboardSegue) {
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("SomeSegue", sender: self)
}
}
you can easily switch between the viewControllers by assigning storyboard id to them using below code ..
// you need to create UIStoryboard object by giving name of your storyboard
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
// here you need to create storyboard ID of perticular view where you need to navigate your app
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"viewContIdentifire"];
// if use presentViewController this will not enables you to go back to previous view
[self presentViewController:vc animated:NO completion:nil];
**// OR**
// using pushViewController lets you to go back to the previous view
[self.navigationController pushViewController:vc animated:YES];
Or still you want to work with segue so must gain control over them by implementing its delegate method below so they perform accordingly.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"segueName"]) {
// perform segue
[self performSegueWithIdentifier:#"SegueIdentifier" sender:self];
}
}
happy coding .. :)

popToRootViewControllerAnimated when user swipe back

I have view A, view B and view C. I have pushed view B from view A and push view C from view B.
When user tap on back button in view C, I call popToRootViewControllerAnimated so that user won't see view B at all.
Problem is that if user swipe back in view C, they will still see view B. I don't want user to see view B at all and jump directly to view A. How shall I do?
I use xib currently.
You can change stack of NavigationController when ViewController C appears. Use below code:-
NSMutableArray *aMutArr = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
[aMutArr removeObjectAtIndex:aMutArr.count-2];
self.navigationController.viewControllers = aMutArr;
I have removed ViewController B from the stack. So if your user swipes back he will be able to see ViewController A.
you can turn off the swipe back feature
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
in that way the user can only go back by the button that you have provided

How do i handle navigation Back button view hierarchy?

Here is the problem
1) Rootview controller - MYAssetVC-> Embedded with NavigationController here pushing for button to another Addfilevc.
2) Addfilevc Has dropdownTextfield It will push to another vc have tableview selected row will display in the textfield.
3)if i select another value from the dropdown textfield it will push to the vc again there i will select.
Navigation bar back button will navigate to all my view hierarchy i want to handle this one. if i go to same view it should navigate back only once that to the recent visit how to do this.
As i am new to iOS. give any suggestion.
Navigation from 1->2->3
navigation backbtn 3->2->1
if i navigate like this 1->2->3-> backbutton 3->2 again 2->3 backbutton 3->2 again 2->3
IF i navigate now using back it is displaying all my route path it should navigate like 1->2->3> and 3->2->1 if any number of times i perform actions in 2 & 3.
1,2,3 are view controllers.
Create an IBAction for the back button and use popViewController.
[self.navigationController popViewControllerAnimated:YES];
This will help you to go back one page. You have to write this in all the pages where there is a back button and you want to go back one page.
If you want to go back directly to rootViewController, try this:
[self.navigationController popToRootViewControllerAnimated:YES];
And if you want to pop to any specific viewController in the stack, you run a for loop to find the viewController you want to navigate to and then simply popToViewController, like this:
for (UIViewController *viewController in self.navigationController.viewControllers) {
if ([viewController isKindOfClass:[Addfilevc class]]) {
[self.navigationController popToViewController:viewController animated:YES];
}
}
Hope this helps to clear your concept.
EDIT
In swift:
The [self.navigationController popViewControllerAnimated:YES]; will become self.navigationController?.popViewControllerAnimated(true)
The [self.navigationController popToRootViewControllerAnimated:YES]; will become navigationController?.popToRootViewControllerAnimated(true)
And the for loop will be as below:
You can use this if you are using storyboard
let switchViewController = self.storyboard?.instantiateViewControllerWithIdentifier("view2") as ComposeViewController
self.navigationController?.pushViewController(switchViewController, animated: true)
And the for-in loop
if let viewControllers = self.navigationController?.viewControllers {
for viewController in viewControllers {
self.navigationController!.popToViewController(viewController, animated: true);
}
}
Thanks.

How to Force Back Button to Go to First View Controller (swift)

I have storyboard of several view controllers embedded in Navigation Controller.
Due to navigation logic in later views of storyboard, the back button (in the left upper corner, in navigation bar) does not go back to the first view. I am wondering where and how to change this behaviour of Back button of second view only. Appreciate any ideas, examples.
Of course you could implement a custom back button. But there is also a nice way to keep using the default button.
Simply check if the current viewController is still in the navigation stack in viewWillDisappear before you call super.viewWillDisappear(). If it is not, the back button has been pressed. Then you can do the popToRootViewControllerAnimated.
override func viewWillDisappear(animated: Bool) {
if (navigationController?.viewControllers)!.contains(self) {
// back button was pressed
self.navigationController?.popToRootViewControllerAnimated(animated)
}
super.viewWillDisappear(animated)
}
The custom back button appears to be the best solution. The code inside your action method would look like the following in swift:
self.navigationController?.popToRootViewControllerAnimated(true)
//Just change the true to false if you don't want it animated.
I hope this helps (if you had not already found the answer). Cheers!
If you meant to say: Prevent Back Button Navigating to Previous Controller and move to first view controller:
You could do this by creating a custom back button - drag a button in storyboard to the top left of the navigation bar, and wire it up to your view controller. In your custom back button's selector write:
[self.navigationController popToRootViewControllerAnimated:YES]
Assuming you have a view controllers stack like : VC1 > VC2 > VC3, and you want to back to VC1 when tapping back on VC3, then you could set this code in VC2 :
[self.navigationItem setBackBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:#"Back" style:(UIBarButtonItemStylePlain) target:self action:#selector(backToVC1)]];
Then, always in VC2 :
- (void)backToVC1
{
[self.navigationController popToRootViewControllerAnimated:YES];
}

Resources