Pushing to UINavigationViewController - ios

I'm doing a login view, which retrieves data and when everything goes well it should move from Login View (UIViewController) to the Navigation controller(UINavigationController) which in his turn should serve as root view controller and move the user to the main view(UIViewController).
The problem is when i reach to the code that works just fine with me inside other classes, it does nothing here, not even throwing exceptions to handle here's my code
func moveToMainView(){
let navigationControllerView = self.storyboard?.instantiateViewControllerWithIdentifier("NavControllerView") as! UINavigationController
self.navigationController?.pushViewController(navigationControllerView, animated: true)
}
I searched to find if there any special case for UINavigationController, but no luck so far... hope you can help me

I've worked around the issue and placed the log-in view controller after the UINavigationController, and because there's usually no navigation bar at the log-in view, i've hidden the navigation bar and showed it back again after the user logged in "when showing the MainViewController".
Hope this work around helps other people that run to this problem

Related

Why my navigation controller make transitions modally instead of push now?

Looking for help with some problem which i clearly don't understand since i'm just beginner here so please help me out if you can.
Here is my issue, so far i built all views through storyboard and all are showed by navigation controller using "push" segue set up in storyboard, till now everything worked as expected.
In some point i decided to add calendar view in the bottom half part of the main view controller to show up when user press the button. Following some advices found online i decided to add it as a child view controller (and did it programatically).
Here is the code i used to present the view:
addChild(calendarVC)
view.addSubview(calendarVC.view)
calendarVC.didMove(toParent: self)
and here is the code i used to dismiss the view:
willMove(toParent: nil)
removeFromParent()
Everything works great so far, but here is the catch:
after triggering removeFromParent() part, transition between every other view controller changed from push to modal. Almost like i lost connection with navigation controller somehow?
I don't know, and my knowledge level is way too low to figure it out myself, any attempts on finding answer here by searching similar topics also didn't give me any answer i can understand, so hoping someone can shed a light on my problem here.
Thanks
make sure you invoke willMove(toParent: nil) removeFromParent() from child view controller.
Invoking the above functions from a parent view will remove the controller from the Navigation hierarchy.

Proper Login Flow and TabBar VC

I am having a few issues accessing the tab bar from the App Delegate to setup the Home Screen Quick Actions. Here is the line of code that I am using to access the tab bar. It is returning false.
guard let tabBarController = self.window?.rootViewController as? UITabBarController else {return false}
My tab bar is not my initial VC when the app launches. I have a loading screen during which we authenticate the user token and then it goes to either the login screen or the tab bar controller (which is also the main part of the app) depending on whether the token gets authenticated.
What is best practice for setting up an app with a login screen? The way we are doing it now works fine but I can change it if there is a better way. We are also using Branch for deep linking.
This is a opinion based question and might exist multiple answer to it each of which might be suitable for some specific scenario.
Approach 1 :
This is my personal Favorite does not mean that this is the only proper way of doing it. I prefer replacing the application's rootView Controller either with LoginVC or TabBarVC based on wether the token is valid or not. There are multiple answers in SO explaining how can u replace the application's rootVC with proper animation. Pasting the same code would be redundant here.
Why I use this approach?
Keeps my applications navigation controller stack clean and I don't keep any additional VC's in memory than whats actually required.
Approach 2 :
This is what many people use for the simplest reason that its simple to use but I personally doesn't prefer it. Modally present either Login VC or Tab bar (both of them might be embedded with UINavigationController obviously and you modally present their NavController's which obviously loads its embedded view controller).
Pros:
Easy to code.
You can always be sure that app's rootVC is always fixed and it has presented either LoginVC or TabBarVC. So parsing and accessing the VC's becomes fairly simple.
Cons:
The Landing VC which modally presents unnecessarily remains in Applications Navigation stack through out the apps life cycle. I clearly don't favor this.
EDIT :
As OP has clearly mentioned that he is using approach 2 and wants to know how to access specific VC in tab bars selected index am updating the code show the same.
Code is not intended for Copy paste, code might contain syntactic error. Code provided below is only intended for providing the idea.
Assuming your LandVC does not have UINavigationController embedded to it.
if let landVC = UIApplication.shared.keyWindow?.rootViewController {
if let presentedVC = landVC.presentedViewController {
if presentedVC is LoginVC {
//this is login VC
}
else if presentedVC is UITabBarController {
let currentlySelectedVC = (presentedVC as! UITabBarController).viewControllers?[(presentedVC as! UITabBarController).selectedIndex]
//now check what type VC it is and use it accordingly
}
}
}

Back button on iOS app not working properly after using popViewControllerAnimated

I've created an app using storyboard. I have few view controllers with navigation controllers. Now in the last of them I have a button, which is opening instagram login view controller (I'm using this library: https://github.com/OceanLabs/InstagramImagePicker-iOS ).
Here's a piece of code:
let loginVC = OLInstagramLoginWebViewController()
loginVC.redirectURI = GlobalConstants.instagramRedirectId
self.instagramLoginViewController = loginVC
self.instagramLoginViewController!.delegate = self
self.navigationController!.pushViewController(loginVC, animated: true)
Then it shows login view controller, I can type in user/password and finally it calls delegate that user was logged in, where I do this:
if(self.instagramLoginViewController != nil){
self.navigationController!.popViewControllerAnimated(false)
self.instagramLoginViewController = nil
}
And it actually pops login view controller, however something strange things are happening from now.
When previous view controller shows up (yes I have it on the storyboard as well as the others) back button doesn't work as it should. On the navigation bar things are changing, but the rest of the screen is not changing until it reaches the very first view controller.
I've checked code inside login view controller from that instagram library and removed that line:
[self.navigationItem setHidesBackButton:YES];
So the back button appears in login view controller too and when I click it everything work. So my conclusion is popViewControllerAnimated is the one, which cause the problem.
How should I fix that?
Damn, I don't know why, but I've changed
self.navigationController!.popViewControllerAnimated(false)
to
self.navigationController!.popViewControllerAnimated(true)
And now it works.. Strange.. I wanted to do it without an animation, but well..

My iOS app complains about two-staged rotation but I'm not using it

I have to support down to iOS 4.3.
My app outputs in the console :
Using two-stage rotation animation. To use the smoother single-stage animation, this application must remove two-stage method implementations.
As far as I know I'm not using two-staged rotation. I just have this method in my view controllers :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
What else should I check in order to fix that?
Edit:
More precisions: my app uses a UITabbarController subclass. When the app starts, it checks if a user is logged in and then initiates the controllers of the tabbar controller if it's the case. If there's no user logged in, a modal view is presented (from the tabbar controller) the prompt the user to login and the controllers of the tabbar controller aren't initialized (yet). The "two-staged rotation" error is shown only at that moment and the rotation doesn't work.
So to summarize, the problem happens in that situation:
The rootViewController of the main window is the tabbar controller
The tabbar controller is empty (there are no view controller in the tabs and there's no tab)
A view controller is modally presented from the tabbar controller
OK I found a solution.
It seems like the presented modal view won't rotate until the viewControllers property of the UITabBarController is initialized. Since the concerned modal view is actually for login, I don't want to display anything behind it until the user is logged in because the views intended to be hold by the tabbar controller depend on the fact that a user is logged in.
So now just before presenting the modal view, I initialize the tabbar controller with a single, empty UIViewController and I remove it when the modal view is dismissed (i.e. a user logged in).
Perhaps it seems like a hack but it works well. And even if I don't understand why, it doesn't seem completely illogical that the tabbar controller doesn't behave like we want until it is fully initialized.
If someone has a better solution or explanation, feel free to comment :)
There aren't many posts regarding this error, so I'll admit my own shortcomings for the benefit of the next person so focused on the trees they might miss the forest. I found a missing
[super viewWillAppear:animated];
call inside my sub.

Push to iOS NavigationController from inside Modal View

I'm new to iOS programming and also to Stack Overflow. I've been trying to find an answer to my question, but searching hasn't yielded any results.
I'm trying to get the flow of my application down, but I'm running into issues. What I would like to have happen is this:
Initial view (NavigationController) -> Searching view (modal) -> programatically push different views onto the initial view's NavigationController from withing the searching view before dismissing the view.
My understanding is that inside the modal view, I should be able to do something like
[self.parentViewController.nagivationController pushViewController: someView]
but that doesn't work at all. After dismissing the modal view I'm just back at the initial view.
I've also attempted to pass a reference to the initial view navigation controller, but I can't seem to make that work right.
So if anyone knows how to programatically push views onto a navigation stack from inside a modal view, I'd love to learn! I'm really starting to think that my understanding of modal views is fundamentally flawed.
Thanks in advance for any help you can provide, and also your patience with a complete newb.
Annnnnd, I'm dumb.
I had the right approach, but it took me a day to realize that self.parentViewController returns a UINavigationController, so the extra ".navigationController" was completely unnecessary.
Correct reference:
[self.parentViewController pushViewController: someView]
Thanks for commenting, Rob.
parentViewController returned nil, but using presentingViewController worked. Swift 2.x:
let vc = storyboard!.instantiateViewControllerWithIdentifier(CustomViewControllerID) as! CustomViewController
if let navController = presentingViewController as? UINavigationController {
navController.pushViewController(vc, animated: false)
}

Resources