Back button on iOS app not working properly after using popViewControllerAnimated - ios

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..

Related

Having Trouble Navigating Between UIViewControllers

Let me start by saying that I want to do all of this without storyboards. My situation is as follows: I have a login page for the user. On the login page the user can login, or be taken to a register page. When the user registers successfully, they are taken to the main menu. However, if I they click logout from the main menu, dismissing the main menu viewcontroller takes me back to the register page (which makes sense).
The problem is I need to take the user to the login page. However, I cannot present the original login page because I get the error "Warning: Attempt to present on which is already presenting "
Is there some sort of way for me to dismiss 2 view controllers? Or maybe run a line of a code on a view controller if it is presented from a certain view controller?
Thank you!
This is the solution that I used from the main menu and it worked
if(self.presentingViewController == registerPage){
registerPage.dismissViewControllerAnimated(true, completion: nil)
}
self.dismissViewControllerAnimated(true, completion: nil)
If you are using a navigation controller, you can get the viewControllers array property, build up a new array without the viewControllers you want to dismiss and set the property with the new array.
No need to switching to Navigation controllers.
If you are presenting view controller than simply try this:
For Objective-C:
[[[self presentingViewController] presentingViewController] dismissViewControllerAnimated:YES completion:nil];
For Swift:
self.presentingViewController!.presentingViewController!.dismissViewControllerAnimated(true, completion: {})
Hope it will work for you.

Pushing to UINavigationViewController

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

First time launch/Has logged Storyboard View Controllers Swift

I have a Page View Controller as an introduction tutorial off to the side. My Login/SignUp VC's segue to the Tab Bar Controller. Which is my home.
Here's what I am trying to accomplish:
If it's the users first time launching the app, go to the Page View Introduction which leads them to the Login/SignUp.
If the user has logged in before, then go to the home screen of the tab bar controller.
My Login/SignUp view controllers are the set to the initial view controllers. (I use Parse if that matters). I'm guessing I should set the Page View introduction tutorial as the initial view controller? I can link the Login/SignUp VC's to the Page View but don't really know where to go from there. All the answers I've found have been in Objective C, which doesn't help.. Thanks!
What you want is called NSUserDefaults, you can read about it here:
It works as a key-value mechanism that will store data in your app. When you finish launching the app (applicationDidFinishLaunchingWithOptions in app delegate) you can do something like this:
let defaults = NSUserDefaults.standardUserDefaults()
if defaults.objectForKey("userAsLoggedInBefore") {
//here you insert the code to go to the home screen
} else {
//this means the user hasn't logged in before and you can redirect him to the registeration page
}
To set the "User Logged In Information", you just have to put the following code when you want it to happen (in this case after the first sucessfull login)
NSUserDefaults.standardUserDefaults().setObject("1", forKey: "userAsLoggedInBefore")
If you need any more help, just say and I'll try to help you.

remove all uiviewcontroller from hierarchy to display the first uiviewcontroller

When my App is starting I have a modal view controller to enter credentials (IP#, username, password...). When the user is logged he can open many UIViewControllers that can open others UIViewController and so on... These view controller can be navigation controller, tab bars, modals....
Next, the user can leave the application in background. Next, user can open the Mail App and open a mail that contains an attachment to navigate to my App. When the user select my App to open the attachment.
When the App moves in foreground I need to go to a specific viewController of the hierarchy (the first ViewController opened after the login screen).
To move the App to this first ViewController I have tried to use
– dismissViewControllerAnimated:completion:
but without success, there're still a view from the hierarchy that is still displayed.
Any idea how to do this?
Regards,
Sebastien.
If all the view controllers are in 1 Navigation controller and pushed onto the stack, you can simply use either popToRootViewControllerAnimated: or popToViewController:animated:
Otherwise, why not dismiss the first Modal view controller, then put it back with the view controller you want.
I found a solution with this small piece of code
UINavigationController* navc = (UINavigationController*)viewController.topViewController;
if (navc != Nil) {
if (navc.presentedViewController != Nil) {
[navc dismissViewControllerAnimated:FALSE completion:Nil];
}
[navc popToRootViewControllerAnimated:TRUE];
}
It was not complex at the end!
Sébastien.

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.

Resources