I'm new to iOS and trying to build one AR app with navigation bar, I defined 3 viewcontroller in the app, and using storyboard and navigation bar to switch the viewcontrollers:
VC1 - Home view, there is one button navigated to VC2;
VC2 - this view controller will call camera to scan image marker; when the image was identified, I just instantiate VC3 programmatically.
VC3 - just showing some information for the image, I added 2 buttons here which will navigated to VC1 and VC2 seperately.
So VC1->VC2, VC2->VC1 are OK as the navigation bar configuration, the problem is when I click button in VC3 to VC1 or VC2, both navigation bar in VC1 and VC2 disappear. It seems I missed some configuration here, can anyone tell me how to make the navitation bar always there?
You can check navigationBar's visibility in method viewDidAppear of VC1 and VC2 like this:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(#"navigationBar is hidden:%#\n",
self.navigationController.navigationBar.hidden ? #"YES": #"NO");
}
It should be YES in VC1 and VC2, you probably change navigationBar's visibility in somewhere, find it then fix it.
I have solved my problem from below link, it is working perfectly
Change destination of Navigation Back button
Related
I have a UITabBar with four tabs. My second tab has two child navigation controller like 2nd tab -> child VC1 -> child VC2.
Now when I go to child VC1, i want to disappear/hide the bottom tabbar & if I go to child VC2 from VC1, the bottom tabbar should be shown again.
If I back from VC2 to VC1, the tabbar will be disappear and then again back from VC1 to 2nd tab controller, the tabbar should be appear again.
How can I achieve this thing ?
In the storyboard, I selected "Hide Bottom Bar on Push" for the child VC1, the tabbar is disappear on this controller but the problem is when I go to child VC2 from VC1, the tabbar still disappear.
How can solve this issue ? Thanks.
In VC1
-(void)viewWillAppear:(BOOL)animated {
self.tabBarController.tabBar.hidden = YES;
}
In VC2
-(void)viewWillAppear:(BOOL)animated {
self.tabBarController.tabBar.hidden = NO;
}
As shown in the photo below, I have a TabBar controller as my root view controller with some navigation controller attached to it. In my VC1 and VC2, I have the tab bar and navigation bar on screen which is what I want, However, for VC3, I do not want tab bar. Currenty I am just hiding and unhiding the tabbar at view will appear. However, this presented some poor user interface. What I think would be great is when I present VC3, it just present "over" the current screen whilst keeping the navigation bar. Is it possible to do that? I'd also like the presentation to be from right to left just like a segue (As oppose to show from bottom)
Note. I use performSegueWithIdentifier for going to VC3
I have seen some solution where I have to set the rootVC to be a normal view controller instead (A login VC in my case) . However, I am trying to avoid that because If the user has already logged in, I do not need to present the login. If I have that as my rootVC all the time, the user will be forced to load and "see" the login VC first before seeing the tabBarVC. This will cause. Unless there is a way to get away with it?
FIRST WAY : PUSH
You can hide bottom bar on push by enabling the flag of VC3 from storyboard.
Please refer following picture:
SECOND WAY : PRESENT
Set a navigation controller for VC3 and present that navigation controller from VC1 or VC2 or TabBar as shown in following image :
You can create a new window, then present your VC3 on it, this would ensure it's over tabbar, in exchange of making new navigation controller and fake back button. But I'd rather check the hide tabbar on push option in storyboard, it give the tabbar hiding a nice animation
For your second question, the best way is make the rootVC in storyboard the tabbar controller, and separate the loginVC, in AppDelegate, check for user login or not and set the rootVC to loginVC or tabbar controller
When first time you login, you have to set the root view controller as login view controller.Then in viedDidLoad method you have to set check already logged in or not.When first run your app it has not logged in so you can go login page.Once you logged in you can go to next page directly.You can use LoginViewController viewDidLoad method.
- (void)viewDidLoad
{
[super viewDidLoad];
BOOL loggedIn = [[NSUserDefaults standardUserDefaults] boolForKey:#"logged_in"];
if(loggedIn)
{
NSLog(#"It has already logged in so go to next view");
}
}
When you login successfully set the bool to YES
- (IBAction)actionLoggin:(id)sender
{
if ([strUsername isEqualToString:#"xxxxxx"] && [strPassword isEqualToString:#"xxxxxx"]) //If it is correct
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"logged_in"];
}
}
Then when you log out,set the bool to NO
- (IBAction)actionLoggin:(id)sender
{
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"logged_in"];
}
1>For tab bar you can delete Tabbar or you can Hide Tabbar from storyboard but don't take separate nav controller for VC3.
You can kept navbar item title value of VC3 as VC2 or VC1 navbar title while pushing or presenting VC3.For that you have to user performseguewithidentifier and initialise VC3 nabber item title value
2> Hey for user is already login then in appdelgate you can change root view controller.By finding user is logged in or not from user default.
you can change rootviewcontroller using window.rootviewcontroller and while doing log out you again can change rootviewcontroller.
In my image, my first Tabbar is HomeViewController and the second Tabbar is CameraViewController.
What is the proper way to segue to the Tabbarcontroller? You can see the read line, I try to segue this but I
always get the back button in my HomeViewController and It display weird like not showing the navigation name.
In CameraViewController I hide the Tabbar for the use camera button. I try to use segue programmatically like this one.
[self performSegueWithIdentifier:#"sample" sender:sender]
but It doesn't work properly. Is this possible to segue to TabbarController?
You can't call
[self performSegueWithIdentifier:#"sample" sender:sender]
Because you're in TabBarController already. You could implement custom flow. By pressing "Back" button - just show TabBar and change selected tabBarItem for example…
update
used this
[self.tabBarController setSelectedIndex:0];
A UINavigationController's navigationBar will initially show the correct UINavigationItem, but then will revert to the previous UINavigationItem every time a UIViewController is pushed onto the stack.
Steps to Reproduce:
Push a UIViewController onto a UINavigationController stack
Set navigationBarHidden = YES on the navigation controller
Push another view controller onto the navigation stack.
Begin an interactive pop transition and then cancel it.
Pop back to the previous view controller
Set navigationBarHidden = NO on the navigation controller
Attempt to push a view controller onto the stack
Looks like -[UINavigationBar _cancelInteractiveTransition] is getting called, even on push transitions after getting into this state? I can set a breakpoint on that symbol, and the navigation bar shows the correct navigation item before it and the wrong navigation item afterwards.
But what I want is that the navigation controller's navigation bar should display the current topViewController's navigation item.
#interface UINavigationController (Private)
- (void)_cancelInteractiveTransition:(float)arg1 transitionContext:(id)arg2;
#end
- (void)_cancelInteractiveTransition:(float)arg1 transitionContext:(id)arg2
{
BOOL hidden = self.isNavigationBarHidden;
if (hidden) {
[self setNavigationBarHidden:NO animated:YES];
}
[super _cancelInteractiveTransition:arg1 transitionContext:arg2];
if (hidden) {
[self setNavigationBarHidden:hidden animated:YES];
}
}
I recently ran into this issue on iOS10 and I'm sure it was there on iOS9, assuming we still supported it. It turned out that the issue was that at the start of the interactive transition we were setting navigationController.navigationBarHidden=NO and then when it was cancelled forgetting to set it back to navigationController.navigationBarHidden=YES. It seems like the navigation bar doesn't like to be unhidden twice in a row. I would imagine that its the same for setting it to hidden twice in a row as well. The good news is that this was not an issue with iOS11.
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];
}