iOS unwind to view not loaded - ios

I'm in front of a little problem :
I have something like that when launching the app :
(1) Splash view --> I am logged ? --> (3) HomeView | else (2) Login view
So when I log, then I go to the home view. And when I logout, I can unwind to the login view because i came from it.
BUT if I don't pass from the login view and redirect directly to the home view, I can't unwind to login view when logout.
Someone know a solution about this ?

I just put my logic here:
Take/add one viewController such like, DummyViewController as rootViewController of your app.
in the DummyViewController's viewWillAppear method put logic like a
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if(login == YES)
{
//go to home screen
}
else
{
// go to login screen
}
}
In DummyViewController you just need to write code in viewWillAppear not anymore.
If you want to Logout then just call
[self.navigationController popToRootViewControllerAnimated:YES];
And viewWillAppear method of DummyViewController will manage your screen based on login status.

You can use NSNotificationCenter to notify your root class when logout done. Then pop to your rootViewController
If you are using UINavigationController, Just present your login controller on NavigationController's RootViewController as like below
-(void)logoutNotification
{
logout = YES;
}
-(void)viewDidAppear:(BOOL)animated
{
if (logout)
{
AuthController * auth = [[AuthController alloc] init];
[self presentViewController:auth animated:NO completion:^{
}];
logout = NO;
auth = nil;
}
}

Maybe is a bit dummy way to do it, but you can simply ALWAYS load the login view and delegate to it the "I'm logged?" check. You can load it hidden or with a waiting sign or whatever... This way you have it already loaded when you logout.
Without seeing your code I can't show you how to, but I guess the logic is enough.

Related

Add Login View before Tabbar Content ViewController

I have the following requirements:
A Tabbar Navigation, with 2 "Tabs" that include a Login. So if a user tab (for example) an Button3 of the UITabBar ill get a fullscreen login view - But only on 2 specific tabs.
This is the workflow:
If there is an active session (i am using a login session management) - i will not present a login button - but if there is none, a login window should appear in fullscreen.
So when ill now show in any of the RootViewControllers in ViewDidLoad the loginViewController, the "content" of the rootViewControllers still get loaded.
So ill my opinion ill should handle after click on a button, WITHOUT loading the RootViewController for that tab.
Can anyone help me whats the best approach to solve such things?
You can use -(BOOL)tabBarController:shouldSelectViewController: method of UITabBarDelegate to handle tab selection and present login view instead of activating tab if needed.
You'll possible need to store a callback (i. e. block), in which you activate tab manually using tabBar.selectedIndex = index.
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
NSInteger index = [_tabBarController.viewControllers indexOfObject:viewController];
if (index==4)
{
if (_authorized)
{
return YES;
}
else
{
[self authorize];
__weak UITabBarController *tabBarController = _tabBarController;
_authorizationCallback = ^(){
//
tabBarController.selectedIndex = 4;
};
return NO;
}
}
return YES;
}

Unwind segue doesn't work sometimes

I have a bunch of views inside of a Nav controller.
The view hierarchy is LoginView -> NAV -> View 1 -> (present a VC. then dismiss) -> push V2 -> push V3 etc
At any view (V1, V2, V3 etc) there is a button that pushes the "Settings View". Inside the settings view there is a logout button.
In SettingsVC.m:
- (IBAction)logout:(id)sender {
NSLog(#"logging out");
// do things here
[self performSegueWithIdentifier:#"UnwindToLogin" sender:self];
}
In LoginVC.m:
- (IBAction)unwindToLogin:(UIStoryboardSegue *)unwindSegue {
self.emailField.text = nil;
self.passwordField.text = nil;
self.loadingSpinner.hidden = YES;
self.failureLabel.hidden = YES;
self.loginButton.userInteractionEnabled = YES;
NSLog(#"unwinding?");
NSLog(#"I hate unwinding");
}
I have hooked up the button in SettingsVC to logout:sender:. When I press the button it logs "logging out" and does all the things inside of the method, but it doesnt unwind to the LoginVC.
[Note: It is often the case that the Application launched and never loaded the Login View. (If there are stored credentials, it skips that view and logs in automatically. But even when the Login View is presented on startup, the unwind sometimes doesnt work.]
[Note 2: Often (but not always), if the last method I edit before running the app is unwindToLogin: the unwind works]
Please help
It seems that sometimes the Login Controller wasn't loaded at unwind time and therefore couldnt be unwinded back. Instead, I unwind to the landing VC which comes before the login, and immediately segue to the login VC

dismissViewControllerAnimated doesn't dismiss

I am working on an iPad app that has a login controller which segues into a view controller. The login controller is declared thusly:
#interface LoginController : UIViewController <UITextFieldDelegate>
and the storyboard has (as expected), a username and password text field and a button for authentication and logging into the main app. The button calls the shouldPerformSegueWithIdentifier(...) function and the view switches from the login view to the main view.
I would like to also mimic this programmatically, when the user hits return on the password text box. I've trapped the event, but I can't seem to get the switchover to happen. The code I'm using is:
if (theTextField == self.password)
{
BOOL loginSuccessful = [self shouldPerformSegueWithIdentifier:#"switchToViewer" sender:self];
if (loginSuccessful == YES)
{
[self dismissViewControllerAnimated:YES completion:^{
NSLog(#"I should be dismissing here!\n");
}];
}
}
However, the view never gets dismissed. I should note that this is on iOS 7, I don't know if that matters. Any ideas?
EDIT: My workaround for now is to spoof the button touch event:
[self.signIn sendActionsForControlEvents: UIControlEventTouchUpInside];
Hacky, but it works :)
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

iOS: Pushing a view controller with animation only works once

I am creating an iPhone client for one of my apps that has an API. I am using the GTMOAuth2 library for authentication. The library takes care of opening a web view for me with the correct url. However I have to push the view controller myself. Let me show you some code to make things more clear:
- (void)signInWithCatapult
{
[self signOut];
GTMOAuth2ViewControllerTouch *viewController;
viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithAuthentication:[_account catapultAuthenticaiton]
authorizationURL:[NSURL URLWithString:kCatapultAuthURL]
keychainItemName:kCatapultKeychainItemName
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)];
[self.navigationController pushViewController:viewController animated:YES];
}
I have a "plus"/"add" button that I add to the view dynamically and that points to that method:
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(signInWithCatapult)];
When I press the "add" button, what is supposed to happen is to open the web view with an animation, and then add an account to the accounts instance variable which populates the table view. This works fine if I add one account, but as soon as I try to add a second account, the screen goes black and two errors appear in the console:
nested pop animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
The only way that I found to avoid this problem was to disable animations when pushing the view controller.
What am I doing wrong please?
Typical situations
You push or pop controllers inside viewWillAppear: or similar methods.
You override viewWillAppear: (or similar methods) but you are not calling [super viewWillAppear:].
You are starting two animations at the same time, e.g. running an animated pop and then immediately running an animated push. The animations then collide. In this case, using [UINavigationController setViewControllers:animated:] must be used.
Have you tried the following for dismissing once you're in?
[self dismissViewControllerAnimated:YES completion:nil];
I got the nested pop animation can result in corrupted navigation bar message when I was trying to pop a view controller before it had appeared. Override viewDidAppear to set a flag in your UIViewController subclass indicating that the view has appeared (remember to call [super viewDidAppear] as well). Test that flag before you pop the controller. If the view hasn't appeared yet, you may want to set another flag indicating that you need to immediately pop the view controller, from within viewDidAppear, as soon as it has appeared. Like so:
#interface MyViewController : UIViewController {
bool didAppear, needToPop;
}
...and in the #implementation...
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
didAppear = YES;
if (needToPop)
[self.navigationController popViewControllerAnimated:YES];
}
- (void)myCrucialBackgroundTask {
// this task was presumably initiated when view was created or loaded....
...
if (myTaskFailed) { // o noes!
if (didAppear)
[self.navigationController popViewControllerAnimated:YES];
else
needToPop = YES;
}
}
The duplicated popViewControllerAnimated call is a bit ugly, but the only way I could get this to work in my currently-tired state.

iOS: Disable/delete/hide previous ViewController from Segue

In my login logic I have a "AuthenticationViewController" (here the application checks if the user is already logged in). I also use storyboard and all views are based on push segues. And so it looks:
------ AccountViewController
|
--> AuthenticationViewController +
|
------ LoginViewController
Now when I use the UITabbarController and press twice on the tabbar icon "account", the application pops back to the AuthenticationViewController and then to the accountView or to the loginView. I know it's a "blemish" but how can I achieve that when I press twice at the account-icon, the AuthenticationViewController does not get shown? Or do I have a wrong logic?
EDIT
This is how my push-function gets initialized programmatically in the authenticationViewController:
// Delegate to AccountViewController if Data (Username, Password) is correct
if ([strResult isEqualToString:#"1"]) {
AccountViewController *AVC = [self.storyboard instantiateViewControllerWithIdentifier:#"AccountView"];
[self.navigationController pushViewController:AVC animated:NO];
// [self performSegueWithIdentifier:#"authAccountSegue" sender:self];
}
else {
LoginViewController *LVC = [self.storyboard instantiateViewControllerWithIdentifier:#"LoginView"];
[self.navigationController pushViewController:LVC animated:NO];
}
Well there's 2 things I see here, not sure if they'll help towards fixing your problem exactly though. The first is that you could just set up the segues for both actions and there wouldn't be much difference. The other is that looking at your storyboard structure the Login and Account controllers seem to be more suited to be a modal view instead of pushing it onto the stack.
Ok, solved this problem on my own: SUBVIEWS are the key :)

Resources