How to move to 2nd ViewController after data validation complete - ios

I'm creating a small app which verifies username and password from plist and shows user profile in other ViewController or (next screen).
I added a Login Button which validates username and password from user input with data stored in Plist(property list).
I also added a condition for show alert message when user entered wrong password or logged in successfully.
I created an another ViewController and connects with main ViewController via Login button.
my problem is when i clicked LOGIN button, it automatically moves to next view controller without checking username password and also not shows alert.
how to go next ViewController after validation completes and alert view done.
I need code in Objective-C
- (IBAction)submitButton:(UIButton *)sender {
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"profileDetails" ofType:#"plist"]];
NSString *usernameentered = dict[#"user"][#"username"];
NSString *passwordentered = dict[#"user"][#"password"];
if ([self.username.text isEqualToString:usernameentered] && [self.password.text isEqualToString:passwordentered]) {
NSLog(#"login sucessfull");
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"Attention"
message:#"LOGIN SUCCESS"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"OKAY" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}else if ([self.username.text isEqual:#""] && [self.password.text isEqual:#""]) { UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"Attention"
message:#"PLEASE ENTER Valid EMAIL AND PASSWORD"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"Okay ! Got it" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}
}

I think you have use 'show' segue in tap of login button tap.you need to use custom segue for it. You can setup custom segue as below.
Step 1:
Give custom segue to current controller to target controll. You can also see in below image.
Step 2
- Give any unique identifier to segue. You can also see in below image.
Then use below code for redirection when credential is valid.
[self performSegueWithIdentifier:#"NextVC" sender:self];

"i created an another view controller and connects with main view controller via Login button"
If you're using segue to navigate then you should write code inside prepareForSegue or shouldPerformSegueWithIdentifier method. Otherwise you can navigate to ViewController through code inside submit button action.
Try writing this code inside shouldPerformSegueWithIdentifier method, it should work

- (IBAction)submitButton:(UIButton *)sender {
//Get stored username and password
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"profileDetails" ofType:#"plist"]];
NSString *usernameentered = dict[#"user"][#"username"];
NSString *passwordentered = dict[#"user"][#"password"];
if ([self.username.text isEqual:nil] || [self.username.text isEqual:#""]) {
//Show alert for empty username
}
else if ([self.password.text isEqual:nil] || [self.password.text isEqual:#""]) {
//Show alert for empty username
}
else if (![self.username.text isEqualToString:usernameentered]) {
//Show alert for wrong username
}
else if (![self.password.text isEqualToString:passwordentered]) {
//Show alert for wrong password
}
else {
//All validation is right.
//Move to other Viewcontroller
UIStoryboard *main = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
NSString *Identifier = #"ViewController"; //Same as in storyboard
UIViewController *vc = [main instantiateViewControllerWithIdentifier:Identifier];
[self.navigationController pushViewController:vc animated:true]; //If you want to push
//[self.navigationController presentViewController:vc animated:YES completion:nil] //If you want to present
}
}

Related

Is there any delegate that serves the purpose of tabBar willSelectItem?

I need to do some UI tasks when user selects a UI tab item. Following delegate is available,
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
Although, to answer for my particular question the internal UI transition issue is not important here, I am still sharing a overview code snippet.
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[delegate.rootTabBarController showConsentErrorPage];
}
However, my UI task inside this delegate shows a glitch on the transition as it does the work after the tab is already shown. I want to perform the UI task first before the UI being visible. Any such delegate of trick to resolve this issue?
This may help you (without additional information, I can't really say).
subclass UITabBarController conforming to <UITabBarControllerDelegate>
in that new custom UITabBarController , be sure to set self.delegate = self; in viewDidLoad
implement shouldSelectViewController
if that controller is your "needs consent to see" view controller,
check if the user has already given consent
if so, return YES (i.e. allow the tab to be selected)
if not, present your "Ask Consent" controller and return NO
if the user gives consent, navigate to that tab
Here is some sample code...
With this option, we present the "Ask Consent" controller, and only navigate to the "needs consent to see" tab when the user selects "Yes":
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if ([viewController isKindOfClass:NeedsConsentViewController.class]) {
NeedsConsentViewController *vc = (NeedsConsentViewController *)viewController;
// whatever you're using to track the user's consent
if (vc.hasConsent) {
// allow the tab to be selected
return YES;
}
// configure / instantiate your "Consent" view controller
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:#"Yes/No"
message:#"Need your consent..."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okButton = [UIAlertAction
actionWithTitle:#"Yes"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
// however you're setting your user consent tracking
vc.hasConsent = YES;
// show that tab
[self setSelectedViewController:vc];
}];
[alert addAction:okButton];
UIAlertAction* noButton = [UIAlertAction
actionWithTitle:#"No"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
// user said NO... nothing else to do
}];
[alert addAction:noButton];
[self presentViewController:alert animated:YES completion:nil];
// don't show the tab
return NO;
}
// all other tabs
return YES;
}
With this option, we present the "Ask Consent" controller and navigate to the "needs consent to see" tab behind it. If the user answers "No" we navigate back to the previously selected tab:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
NSInteger curTabIDX = self.selectedIndex;
if ([viewController isKindOfClass:NeedsConsentViewController.class]) {
NeedsConsentViewController *vc = (NeedsConsentViewController *)viewController;
// whatever you're using to track the user's consent
if (vc.hasConsent) {
// allow the tab to be selected
return YES;
}
// configure / instantiate your "Consent" view controller
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:#"Yes/No"
message:#"Need your consent..."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okButton = [UIAlertAction
actionWithTitle:#"Yes"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
// however you're setting your user consent tracking
vc.hasConsent = YES;
// we've already navigated to the tab, with the Consent VC presented on top of it
// so nothing else to do
}];
[alert addAction:okButton];
UIAlertAction* noButton = [UIAlertAction
actionWithTitle:#"No"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
// user said NO, so return to the previous tab
[self setSelectedIndex:curTabIDX];
}];
[alert addAction:noButton];
[self presentViewController:alert animated:YES completion:nil];
// show the tab behind the Consent VC
return YES;
}
// all other tabs
return YES;
}
Note: This is Example Code Only and is not intended to be, nor should be considered, "production ready."

IOS/Objective-C: Launch UIAlertController from code in subclassed Class in Storyboard app

Two View Controllers in my app subclass the same class that has common methods. I would like to launch an alertController (fire an alert) from code in a method of this common sub-classed controller. But the following code is not launching anything.
Can anyone suggest the right way to point to the subclassed VC to get the alertController to launch?
Thanks in advance for any suggestions.
View controller1 wired to storyboard subclasses common class as follows:
#interface IDManageItemsVC : IDCommonVC <UIAlertViewDelegate>
The common VC subclasses CoreVC which has even more common methods for the whole app:
#import "IDCoreVC.h"
#interface IDCommonVC : IDCoreVC<UITableViewDelegate,UITableViewDataSource,UIAlertViewDelegate>
I am trying to fire the alert from code in commonVC (the superclass for the class wired to storyboard) as follows:
-(void)fireAlert {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"Delete?" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* yesButton = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
//run code
}];
UIAlertAction* noButton = [UIAlertAction
actionWithTitle:#"Not Now"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
//if chosen run code
}];
[alert addAction:noButton];
[alert addAction:yesButton];
if ([alert respondsToSelector:#selector(setPreferredAction:)]) {
[alert setPreferredAction:yesButton];
}
/* following points to VC not in hierarchy so commented out
id rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
if([rootViewController isKindOfClass:[UINavigationController class]])
{
rootViewController = ((UINavigationController *)rootViewController).viewControllers.firstObject;
}
if([rootViewController isKindOfClass:[UITabBarController class]])
{
rootViewController = ((UITabBarController *)rootViewController).selectedViewController;
}
[rootViewController presentViewController:alertInvite animated:YES completion:nil]; */
//Following does not do anything
[self presentViewController:alert animated:YES completion:nil];
}
Edit:
Using the following method, with a breakpoint, I visually verified that topViewController is the right one and then presented the alertview from it and it still did not display. The only thing I noticed is that when I visually examined the alertview, it appears blank with just a slight white curve in the upper left where a rounded corner might be against a white rectangle. So perhaps, there is something wrong with the way I'm creating the alertview.
UIViewController *currentTopVC = [self currentTopViewController];
currentTopVC.presentViewController.........
- (UIViewController *)currentTopViewController {
UIViewController *topVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
while (topVC.presentedViewController) {
topVC = topVC.presentedViewController;
}
return topVC;
}
and instead of [self presentViewController..., the following:
UIViewController *currentTopVC = [self currentTopViewController];
[currentTopVC presentViewController:alertInvite animated:YES completion:nil];
I copied and pasted your code and replaced
[self presentViewController:alertInvite animated:YES completion:nil];
with
[self presentViewController:alert animated:YES completion:nil];
and it worked.
This doesn't look like a inheritance issue to me. Are you by any chance calling this method from viewDidLoad: or any method that gets called before the view controller is actually shown? If so, try calling it from viewDidAppear:

Dont dismiss UIAlertController

I currently have a UIAlertController that I need to make non-dismissible. The Alert should not dismiss when pressing the action button.
How can I do this?
UIAlertController *alert;
int bestScore = [[[NSUserDefaults standardUserDefaults] objectForKey:#"bestScore"] intValue];
if (!bestScore || bestScore < _score){
[[NSUserDefaults standardUserDefaults] setObject:#(_score) forKey:#"bestScore"];
alert = [UIAlertController alertControllerWithTitle:#"GAME OVER "
message:[NSString stringWithFormat:#"NEW RECORD! \n SCORE : %d \n\n\n\n\n\n", _score] preferredStyle:UIAlertControllerStyleActionSheet];
}
else alert = [UIAlertController alertControllerWithTitle:#"GAME OVER"
message:[NSString stringWithFormat:#"SCORE : %d \n Best score : %d \n\n\n\n\n\n ", _score, bestScore] preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:#"Try again" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self newGame];
[self addNewView];
}]];
[alert addAction:[UIAlertAction actionWithTitle:#"Answer" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[alert viewWillDisappear:NO];
}]];
[self presentViewController:alert animated:YES completion:nil];
I would recommend creating a UIViewController that contains a UIView. Within this UIView you will be able to display your required information and add the custom button actions that you desire.
In order to make the UIView appear like a modal view controller add a UIVisualEffectView with a UIBlurEffectStyle.
This is as simple as creating a conventional view controller using your storyboard/xib adding the required UIView in the interface builder then linking up the associated view controller class. After completing the initial setup and user interface add the following code to viewDidLoad. Furthermore you can perform the required animations etc within viewWillAppear & viewWillDisappear.
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]
UIVisualEffectsView *blurView = [[UIVisualEffectView alloc] initWithEffect:effect];
[self.view insertSubview:blurView atIndex:0];
You can do like this
If you dont want dismiss alertController then You can disabled button actions of it like
alert.actions[1].enabled = NO
This will make your alertController Non-dismissable.
simply present the alertContoller again at the start of the action for alertButton you want it to not dismiss,
[self presentViewController:alertController animated:YES completion:nil];

viewWillAppear UIAlertView not showing

I have two different view controllers, one for a dashboard and one for registration. I do not want the user to be able to interact with anything on the dashboard until the user logs in through an alertview. So every time the user navigates back to the dashboard or presses cancel and they are not logged in, I want the login alert to popup.
This works perfectly in all cases, including when the user hits the back button on the navigation bar in the registration view, but does not work when the user clicks OK on the alert in the registration page.
the dashboard view contains this code:
#property(strong) UIAlertView * alert;
//...
-(void)viewWillAppear:(BOOL)animated
{
user_email = [[NSUserDefaults standardUserDefaults] stringForKey:#"email"];
if ( user_email==nil ){
[self auto_login];
} else //...
}
-(void)auto_login
{
alert = [[UIAlertView alloc] initWithTitle:#"Login" message:nil delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Login",#"Forgot Password",#"Register",nil];
alert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
[alert show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (buttonIndex) {
case 0:
{
self.debug.text = #"Cancel";
[self auto_login];
break;
}
//...
default:
{
self.debug.text = #"Register";
[self nav_register];
break;
}
}
}
-(void)nav_register
{
RegisterProfileController *rvc = [[RegisterProfileController alloc] init];
[self.navigationController pushViewController:rvc animated:YES];
}
The registration view controller contains this code:
-(void)catch_registration
{
NSString *response = [[NSString alloc] initWithData:self.httpdata encoding:NSASCIIStringEncoding];
if( [response isEqualToString:#"OK"] ){
UIAlertView *successAlert = [[UIAlertView alloc] initWithTitle:#"Success" message:#"..." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
successAlert.alertViewStyle = UIAlertViewStyleDefault;
[successAlert show];
}
else //...
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if ([alertView.title isEqualToString:#"Success"])
[self.navigationController popViewControllerAnimated:TRUE];
}
After debugging, I know that after clickedButtonAtIndex runs in the registration view controller, [alert show] runs in the dashboard view controller, and clickedButtonAtIndex does NOT run in the dashboard view controller, but no alert shows up.
Why isn't the alert showing or how can I debug this further?
If clickedButtonAtIndex "does NOT run" as you said, then the delegate might not be set correctly. In addition, you should likely move the code from viewWillAppear: to viewDidAppear: because the view is not in the view hierarchy at that point. Your solution might be a combination of these two issues.

How to navigate with popViewController

I'm new to iOS development and I'm using parse.com as my backend.
I want to navigate from [View Controller 2] to [view Controller 3]
but is not working right.
Here is the code
http://i.stack.imgur.com/t6zZg.jpg
NSString *username = [self.usernameField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *password = [self.passwordField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *email = [self.emailField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([username length] == 0 || [password length] == 0 || [email length] == 0){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Oops!" message:#"Make sure you enter a username, password , and email address!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show]; // This help to show your message successfully!
}
else {
PFUser *newUser = [PFUser user]; // This is a method to create new users
newUser.username = username;
newUser.password = password;
newUser.email = email;
[newUser signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Sorry!" message:[error.userInfo objectForKey:#"error"] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertView show];
}
else {
[self.navigationController popToViewController:_profilePhotoViewController animated:YES];
}
}];
}
}
According to the image you posted, VC3 is not displayed nor pushed to the controller before displaying VC2
This method popToViewController:animated: require that the controller is displayed before and in the controller stack in order to pop the stack back to it
You can achieve what you want by pop to root and then push your view
[self.navigationController popToRootViewControllerAnimated:NO];
[self.navigationController pushViewController:_profilePhotoViewController animated:YES];
Besure that _profilePhotoViewController is allocated before pushing it
.
.
UPDATE
In your storyboard set an identifier to your VC3 to be for example "VC3Identifier"
You can do this as you can see in the below image
Choose your controller
Show the utilities
show the identity inspector
Put 'VC3Identifier' in StoryBoard ID field
Then You will need to allocate a new instance of this controller and add it to the navigation controller
YourController *vc3 = [self.storyboard instantiateViewControllerWithIdentifier:#"VC3Identifier"];
[self.navigationController setViewControllers:#[vc3] animated:YES];
OK, well, I am not totally sure how your code works and what will trigger the change of View, but in your code where you call this:
[self.navigationController popToViewController:_profilePhotoViewController animated:YES];
Is what you need to handle (assuming profilePhotoViewController is VC3).
Go to your Storyboard and ctrl+click+drag from the presenting view (the VC that you are starting from) and end up at VC 3. VC 3 should light up blue. Let go and you will see a drop down menu. Select "Push". This will create a segue for you to transition. Next you need to give it an identifier, so click on the segue that was just made and go to the Attributes Inspector and in the "Identifier" field type in "ProfilePictureSegue" and then press enter (or return).
Then go to the file that contains the code you posted and replace
[self.navigationController popToViewController:_profilePhotoViewController animated:YES];
With:
[self performSegueWithIdentifier:#"ProfilePictureSegue"];
And bob is your uncle. Run it.
EDIT
I looked at your picture again and it looks like your VC3 is in the wrong place. Create a segue from VC2 to VC 3, not from the Navigation Controller to VC3. Call the segue, as I explained above, in the VC2 .m file, and it will transition between.
If you need more explanations.

Resources