I am using this code from Parse:
[PFUser logInWithUsernameInBackground:namerL password:passerL
block:^(PFUser *user, NSError *error) {
if (user) {
[self performSegueWithIdentifier:#"signinToInbox" sender:self];
} else {
NSLog(#"%#",error);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Login Failed." message:#"Invalid Username and/or Password." delegate:self cancelButtonTitle:#"Okay" otherButtonTitles:nil];
[alert show];
}
}];
Whenever I click on the sign in button without typing in anything, it doesn't log any errors. I need it to count it as an error if there is no such user and or if the password is correct. But even if the account details are not correct, it is still going to the segue.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { I believe that it's calling the segue because it is still in didSelectRowAtIndexPath. I just don't know how to stop it from calling the segue that's connected it (by default).
Maybe this problem isn't about parse login at all. From the comments, it seems to be about segues attached to table view cells.
If you want to perform a segue conditionally, it shouldn't be attached directly to the table view cell. Instead draw the segue between view controllers in IB (ctrl-drag from the view controller's status bar to the destination vc). Give that segue a name, like "goodLogin", then perform it manually upon a condition.
So if you only want to segue when a login succeeds ...
// parse login
if (!error) {
[self performSegueWithIdentifier:#"goodLogin"];
} else {
// don't perform a segue. Stay here and change ui to indicate an error
}
This is the code I use:
[PFUser logInWithUsernameInBackground:username password:password block:^(PFUser *user, NSError *error) {
if(!error){
[self loggedInSuccessfully];
} else {
[self loginFailedWithError:error];
}
}];
When doing any API call, I would always check the error variable because if it exists then you know the method failed.
EDIT
From our discussion it appears that you are having problems with your UITableView performing the segue when you click on a cell.
It is possible to disable a segue by returning NO from the shouldPerformSegueWithIdentifier method
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if([identifier isEqualToString:#"signinToInbox"]){
return YES;
}
return NO;
}
This will disable all segues on the UIViewController apart from your signinToInbox
However, I believe you may have your UIStoyboard set up incorrectly, there shouldn't be the default segue enabled. You should only need to perform the segue in the code after you have called the login function. Therefore in the storyboard you should be using the custom segue option.
If you have a segue set up already on the UIStoryboard you should be able to click on it and in the Attributes inspector panel change the drop down from model to custom
It seems you have problems with your segues and table views. Try the following in Xcode 6.
First delete your current segue.
Ctrl + drag as shown:
After that, choose the action segue you want (push, modal or custom). Then make sure the identifier matches the one in the code.
Now simply make the following changes in the code
[PFUser logInWithUsernameInBackground:namerL password:passerL block:^(PFUser *user, NSError *error) {
if (!error) {
[self performSegueWithIdentifier:#"signinToInbox" sender:self];
} else {
NSLog(#"Error logging in: %#",error);
[[[UIAlertView alloc] initWithTitle:#"Login Failed" message:#"In valid username and/or password" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}];
Related
I am programming an IOS app that will use parse to login a user. Using storyboard I have the login button connected to another view controller with the push segue. Whether the username and password are correct the button selection always goes to the new view controller. I might be doing this all wrong. Any help is appreciated. Here is my code:
- (IBAction)signIn:(id)sender {
[PFUser logInWithUsernameInBackground:self.emailField.text password:self.passwordField.text block:^(PFUser *user, NSError *error) {
if (!error) {
[self performSegueWithIdentifier:#"signIn" sender:nil];
} else {
// The login failed. Check error to see why.
}
}];
}
I think the issue is that you connected the button right to the next view controller in your storyboard. Here's what you need to do:
Select the first view controller and create a segue to the second one, NOT from the button, from the first view controller.
In the inspector give the segue an identifier (i.e. "loginSegue").
Create an IBAction for your button by control-dragging the button in the storyboard to the .m file of your first view controller. In that new method you can add the login code:
[PFUser logInWithUsernameInBackground:self.emailField.text
password:self.passwordField.text block:^(PFUser *user, NSError *error)
{
if (!error) {
[self performSegueWithIdentifier:#"loginSegue" sender:nil];
} else {
// The login failed. Check error to see why.
}
}];
I've been developing an iOS app that includes a login screen. This screen has two UITextField where I input the username and the password.
Now, the issue recalls in the following: I've set up an "else if" to trigger an UIAlertView if the field are in blank.
The UIAlertView DOES pop up but... in the next View Controller.
Another issue is... It check if the username and the password are right or not and it jumps into the next View Controller as well.
This is odd because I set an "if" condition to check that the text in both UITextFields must match in order to trigger the next View Controller.
I've got the hunch that another method linked to the login action might be interfering in the process.
I will post the segment of the code concerning the login:
- (void)btn_submit:(id)sender{
NSString *user = self.usuari.text;
NSString *pass = self.contrasenya.text;
NSString * urlBase = #"http://www.v2msoft.com/clientes/lasalle/curs-ios/login.php?username=lluis&password=seguro";
[JSONHTTPClient getJSONFromURLWithString:urlBase completion:^(id json,JSONModelError *err){
JsonUser * user = [[JsonUser alloc]initWithDictionary:json error:nil];
if(user.succeed){
self.user_id = user.user_id;
[self performSegueWithIdentifier:#"Login" sender:self];
}
else{
NSLog(#"error");
}
}];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (([self.usuari.text isEqualToString:#"lluis"]) && ([self.contrasenya.text isEqualToString:#"seguro"])){
Supermarket * supermercat = segue.destinationViewController;
supermercat.user_id = self.user_id;
}
else if (_usuari.text.length == 0 || _contrasenya.text.length == 0)
{
[[[UIAlertView alloc] initWithTitle:#"Alerta!"
message:#"Camps buits!"
delegate: nil
cancelButtonTitle:#"Cancelar"
otherButtonTitles:nil
] show];
}
}
And, also, the few lines of the "JsonUser" class:
#import "JSONModel.h"
#interface JsonUser : JSONModel
#property BOOL succeed;
#property int user_id;
I think that I might be making a mistake by sending the parameters to the server through the URL and that might override the login.
I'd appreciate any help or advice regarding this matter.
It is already too late for your check within prepareForSegue. If you had the chance to stop the presentation of the segue there the method would be called shouldPresentSegue or something like that. Perform your check (the else if) before you call performSegue.
whether u connect segue from submit button to next view controller or segue from login view to nextviewcontroller. Make Sure your segue only from login screen to nextviewcontroller not from submit button.
I've got two labels in a custom UITableViewCell. Their purpose is to indicate the status of a timing operation on the object represented by the cell.
One label displays a countup timer. The other simply blinks "Timer Sleeping." Their visibility is mutually exclusive (if one is visible, the other is not, and vice versa) according to a switch statement to determine which label is currently visible. Each is driven by a dedicated NSTimer.
Everything works fine--until I do a modal segue to another View Controller (for the purpose of adding another entity or other task) and then return to the original VC via Cancel or Savethrough delegation. Then, regardless of which label had been visible (and updating via its timer) prior to the segue, no label is to be seen. The cell appears blank.
The weird thing is that when I segue to yet another VC via a push segue, then return via the "Home" button, the labels appear, blinking or counting up, just as though nothing had happened. The only obvious difference I can see between the two return methods is that the modal is handled via delegation whereas the push is unwound through a nav controller.
Any ideas? I can supply any relevant code, but didn't know where to start and didn't want to paste all of it.
Thanks!
EDIT for clarification in response to question below:
I'm returning via delegation. Here's the code in the modal:
- (IBAction)saveButton:(UIBarButtonItem *)sender
{
if (self.activityField.text.length > 0)
{
if (self.categoryLabel.text.length < 1)
{
// self.thisActivity.category = #"Uncategorized";
// self.thisActivity.name =self.activityField.text;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No category selected"
message:#"Please select a category or Cancel"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
else
{
self.thisCategory.name = self.categoryLabel.text;
self.thisActivity.name = self.activityField.text;
self.thisActivity.category = self.thisCategory.name;
NSLog(#"Category name is %#", self.thisCategory.name);
NSLog(#"Activity name is %#", self.thisActivity.name);
[self.delegate addActivityViewControllerDidSave];
}
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No activity entered"
message:#"Please enter a new activity or Cancel"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
- (IBAction)cancelButton:(UIBarButtonItem *)sender
{
[self.delegate addActivityViewControllerDidCancel:self.thisActivity];
NSLog(#"delegate is %#",self.delegate);
}
And here's the delegate method implementation code from the original VC:
#pragma mark - AddViewControllerDelegate stuff
-(void) addActivityViewControllerDidSave
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[localContext MR_saveToPersistentStoreAndWait];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
[self refreshData];
}
-(void) addActivityViewControllerDidCancel:(WMDGActivity *) activityToDelete
{
[activityToDelete MR_deleteEntity];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
[self refreshData];
}
2nd edit:
Here's the refreshData code:
-(void) refreshData
{
actFRC = [WMDGActivity MR_fetchAllSortedBy:#"category,name"
ascending:YES withPredicate:nil
groupBy:#"category"
delegate:nil];
[self.myTableView reloadData];
}
I've tried calling this method in viewDidLoad, and NOT calling it there. Same results.
UPDATE, 3/26/2014:
OK, I've discovered that if I remove the call to refreshData from my addActivityViewControllerDidCancel method, the labels work fine. They likewise work fine if I remove the same line from addActivityViewControllerDidSave. Unfortunately, this prevents newly added items from appearing in the HomeViewController table view until the app is relaunched.
Here is my current code for the cancel and save methods:
-(void) addActivityViewControllerDidSave
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[localContext MR_saveToPersistentStoreAndWait];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
[self refreshData];
}
-(void) addActivityViewControllerDidCancel:(WMDGActivity *) activityToDelete
{
[activityToDelete MR_deleteEntity];
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[localContext MR_saveToPersistentStoreAndWait];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
// [self refreshData];
}
I view this as a temporary, or interim, fix. Sure would be grateful for a real cure.
Thanks!
I am new to IOS. I am making a login view controller in IOS with one button which is sign in. I have two possible view-controllers that might be shown when the user click on the sign-in button. I am using Storyboard but I can only assign one segue to one button. I don't know how to perform the condition since I seem not to have 100% control over the segue.
Here is my code:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *stringreponse=[[NSString alloc] initWithData:_responseData encoding:NSUTF8StringEncoding];
// NSLog(#"Split response %#", [splitresponse objectAtIndex:0]);
if([stringreponse isEqualToString:#"0"])
{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"Wrong username or password" message:#"Wrong username or password" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
else
{
NSArray *splitresponse=[stringreponse componentsSeparatedByString:#"#"];
if([[splitresponse objectAtIndex:0] isEqualToString:#"Parent"])
{
if([[splitresponse objectAtIndex:2] isEqualToString:#"yes"])
{
//seguechoice=#"showParentRegistration";
//[self performSegueWithIdentifier:#"showParentRegistration" sender:self ];
}else{
//seguechoice=#"showSohoDashboard";
}
}
}
}
you can assign one segue to one UI control but you can assign many to a viewContoller. Simply add all of them to the viewController, give each a different id and then call those id's
if([[splitresponse objectAtIndex:2] isEqualToString:#"yes"])
{
[self performSegueWithIdentifier:#"showParentRegistration" sender:self ];
}
else
{
[self performSegueWithIdentifier:#"showSohoDashboard" sender:self ];
}
Create 2 connection in storyboard from your source view controller to destination view controller (not button). Insert two different identifiers and when the button is pressed do condition and run a segue depends on the condition:
if(CONDITION TO RUN SEGUE !)
{
[self performSegueWithIdentifier:#"SEGUEIDENTIFIER1" sender:self ];
}else {
[self performSegueWithIdentifier:#"SEGUEIDENTIFIER2" sender:self ];
}
I have a viewController class A that have a method creating a UIAlertView and implement UIAlertView Delegate method, and a NSObject model class B for processing logging and networking. In class B, just allocating an A class instance, then call the method of A. The alert view was displayed normally, but when i clicked "Ok" button, it's just crashed. I want click "Ok" button to reopen keyboard let user continue login after failured. (Had declared UIAlertView protocol in header file.)
In viewcontroller class A:
- (void)displayAlertViewString:(NSString *)string
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Login Failured!"
message:string
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"Ok", nil];
[alert show];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if ([title isEqualToString:#"Ok"])
{
//reopen the keyboard let user continue login.
[self.passwordField becomeFirstResponder[;
}
And in model class B, i called display alert view method in the failure block of AFNetworking.
failure:^(AFHTTPRequestOperation *operation, NSError *error){
NSLog(#"%#", error);
RDLoginViewController *loginViewController = [[RDLoginViewController alloc] init];
[loginViewController displayAlertViewString:#"The entered email or password was incorrectly!"];
There is no any information in debugger, Xcode just stuck on the thread view. Can anyone help me figure it out? Thanks.
After the failure block execution, your loginViewController is released from memory, since nobody has a strong reference to it.
When the alertView tries to access it's delegate it crashes, since its delegate is not in the memory anymore.
I'd recommend you to take a look at the Advanced Memory Management Programming Guide.