Chapter    8

The Sign-Up Feature

In the previous chapter, you learned how to alert a user to sign up or log in when adding a product to the shopping bag or to the Favorites list. In this chapter, you implement a dispatch screen that enables users to create an account, log into an existing account, or log in with Facebook. You also learn how to sign up customers. How to implement the direct log in and log in with Facebook features are covered in Chapter 9.

Build a Dispatch Screen

When you implemented the main dispatch feature, you created a different UIStoryboard named LoginSignupStoryboard to reduce the workload of Main.storyboard.

The UI of this DispatchViewController is pretty simple. There are three buttons: the button labeled “Sign Up” is for showing the sign-up screen; the buttons labeled “Log In” and “Log In with Facebook” will be covered in Chapter 9.

To simplify the main view controller, use the segues in the LoginSignUpStoryboard to connect the “Sign Up” button to the EMABSignUpViewController, connect the “Log In” button to EMABLoginViewController, and set up an IBAction for “Log In with Facebook.”

Also provide a “Cancel” UIBarButtonItem in case the user doesn’t want to log in or sign up for an account at this point, so he or she can leave the screen. This LoginSignUpStoryboard is implemented with its own UINavigationController, so you can simply use:

[self dismissViewControllerAnimated:YES completion:nil];

to dismiss the dispatch screen.

Here is the full implementation:

@implementation EMABDispatchViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}

-(IBAction)onFacebookLogin:(id)sender{
    //todo
}

-(IBAction)onCancel:(id)sender{
    [self dismissViewControllerAnimated:YES completion:nil];
}
@end

The Sign-up Model

Let’s jump into the User model, EMABUser, a subclass of PFUser. By default, the EMABUser class has the properties username, password, and e-mail, which are inherited from PFUser; you also may want to collect a little bit more information from the user such as name, address, and photo. Here is the full implementation:

When signing up a user, you only need the user to enter an e-mail address and password. When the user purchases something, you need to know where to ship your products to, so you need to ask the user to enter a shipping address until then. You also provide the Facebook login feature so you can get more information about the user such as a profile photo, gender, region, relationship, and interests. This requires different permissions from the user and Facebook. For now, only ask for the user’s gender and photo.

You also want to override +(PFUser *)currentUser method to return an EMABUser, or Xcode will keep warning you about it.

Here is the EMABUser implementation part:

The Sign-up View

The Sign-Up screen consists of a UITableView, a button with a “Sign Up” title, and a Bar Button Item with the title of “Sign Up.”

UITableView has three cells. For each cell, use a UITextField to capture a user’s input. The first cell is for the registration e-mail, the second cell is for the registration password, and the third cell is for the password confirmation.

Since you will show a similar UITableView with UITextField UITableViewCell, create a UITextField subclass to eliminate redundancies.

First, create the EMABEmailTextField class.

In this implementation, you set the border style, text color, placeholder text, background color, keyboard type and auto correction type, and clear button mode to provide a better UI and user experience.

Next, create EMABPasswordTextField to customize the password TextField look and feel. Here is the implementation:

This looks pretty similar to the EMABEmailTextField; the big difference is that you need to use the secureTextEntry property to hide a user’s input.

Note that it’s not necessary to use a UiTableView with UITextField in UITableViewCell—it just looks nicer. Some developers choose to put three UITextFields on top of a background image with a few separate lines. It also works nicely, if you can find this kind of background image.

The Sign-up Controller

Next, get ready for the EMABSignUpViewController implementation.

First, create the EMABSignUpViewController class as a subclass of UIViewController. There is not too much you need to do with its header file; focus on the implementation file instead. Since you have used UITableView, you need to put the protocol of UITableView in place. You also have UITextField in place, so it’s a good idea to use the UITextField Delegate protocol; this lets you dismiss the keyboard when the user taps the “Done” button. Here is the implementation:

You also need to create three properties to reference EMABEmailTextField and EMABPasswordTextfield. Since you still want to give some room to display each cell’s title, you want to size and position each UITextField. The following code shows how to do that using the -(void) viewDidLoad method.

- (void)viewDidLoad {
    [super viewDidLoad];

    self.emailTextField = [[EMABEmailTextField alloc] initWithFrame:CGRectMake(kLeftMargin, kTopMargin, kTextFieldWidth, kTextFieldHeight)];
    self.emialTextField.delegate = self;
    self.passwordTextField = [[EMABPasswordTextField alloc] initWithFrame:CGRectMake(kLeftMargin, kTopMargin, kTextFieldWidth, kTextFieldHeight)];
    self.passwordTextField.delegate = self;
    self.passwordAgainTextField = [[EMABPasswordTextField alloc] initWithFrame:CGRectMake(kLeftMargin, kTopMargin, kTextFieldWidth, kTextFieldHeight)];
    [self.passwordAgainTextField setPlaceholder:NSLocalizedString(@"Password Again", @"Password Again")];
    self.passwordAgainTextField.delegate = self;
}

Keep in mind that kLeftMargin, kTopMargin, kTextFieldWidth, and kTextFieldHeight are defined in the EMABConstants class. You will need them again in other instances.

Next, move to the implementation of UITableViewDataSource methods. You need one section and three cells for this UITableView.

#pragma mark - tableview datasource
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 3;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

Having set the identifier “SignUpCell” in the nib file on UIStoryboard, here is how you create three cells:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = nil;

    cell = [tableView dequeueReusableCellWithIdentifier:@"SignupCell" forIndexPath:indexPath];

    UITextField *textField = nil;
    switch (indexPath.row) {
        case 0:
            textField = self.emailTextField;
            break;
        case 1:
            textField = self.passwordTextField;
            break;
        case 2:
            textField = self.passwordAgainTextField;
            break;
        default:
            break;
    }

    // make sure this textfield's width matches the width of the cell
    CGRect newFrame = textField.frame;
    newFrame.size.width = CGRectGetWidth(cell.contentView.frame) - kLeftMargin*2;
    textField.frame = newFrame;

    // if the cell is ever resized, keep the textfield's width to match the cell's width
    textField.autoresizingMask = UIViewAutoresizingFlexibleWidth;

    [cell.contentView addSubview:textField];

    return cell;

}

The last piece is to handle one of the delegate methods of UITableView. You don’t really have to implement it.

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}

As you can see, it’s pretty easy to set up your views. However, signing up a user requires a little bit of extra work.

First, you need to check whether the user provides a valid e-mail address. You can use the -(BOOL)isValidEmail method:

#pragma mark - helper
-(BOOL)isValidEmail {
    //https://github.com/benmcredmond/DHValidation
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    return [emailTest evaluateWithObject:self.emailTextField.text];
}

Next, you want to remind the user when there is something wrong with the e-mail entered; use UIAlertView for this. Later you will also show other alert information such as the password length or sign-up errors. Let’s create a -(void)showWarning:(NSString *)message helper method:

-(void)showWarning:(NSString *)message {
    [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Warning", @"Warning") message:message delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"OK") otherButtonTitles:nil , nil] show];
}

Lastly, you also want to allow the user to dismiss the software keyboard, so you implement the UITextField delegate method as follows:

#pragma mark - UITextField Delegate
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}
@end

Next, implement the IBAction when a user taps the “Sign Up” button. Check whether the two password UITextField cells meet the minimum text length requirements; and whether the two text fields have identical text. Also make sure the text length in Email UITextField meets the requirement of minimum text length and is a valid e-mail address. If something is wrong with the information entered, the related warning will be provided afterward. Lastly, use [PFUser user] to create a user instance and cast it to the EMABUser. The username and e-mail of this user are the text in the e-mail UITextField text, and the password of the user is the text in the password UITextfield cell; then you use the Parse -(BFTask *)signUpInBackground method. Here is the complete implementation:

-(IBAction)onSignup:(id)sender{
    BOOL cont0 = [self.passwordTextField.text length] > kMinTextLength;
    BOOL cont1 = [self.passwordAgainTextField.text length] > kMinTextLength;
    BOOL cont2 = [self.passwordTextField.text isEqualToString:self.passwordAgainTextField.text];
    BOOL cont3 = [self.emailTextField.text length] > kMinTextLength;
    BOOL cont4 = [self isValidEmail];

    if (!cont0) {
        [self showWarning:NSLocalizedString(@"Password at least 6 characters.", @"Password at least 6 characters.")];
    }
    if (!cont1) {
        [self showWarning:NSLocalizedString(@"Password at least 6 characters.", @"Password at least 6 characters.")];
    }
    if (!cont2) {
        [self showWarning:NSLocalizedString(@"Passwords have to match.", @"Passwords have to match.")];
    }
    if (!cont3) {
        [self showWarning:NSLocalizedString(@"Email at least 6 characters.", @"Password at least 6 characters.")];
    }

    if (!cont4) {
        [self showWarning:NSLocalizedString(@"Doesn't look like a valid email.", @"Doesn't look like a valid email.")];
    }

    if (cont0 && cont1 && cont2 && cont3 && cont4) {
        [self.emailTextField resignFirstResponder];
        [self.passwordTextField resignFirstResponder];
        [self.passwordAgainTextField resignFirstResponder];
        EMABUser *user = (EMABUser *)[PFUser user];
        user.username = [self.emailTextField text];
        user.email = [self.emailTextField text];
        user.password = [self.passwordTextField text];
        [user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error){
            if (!error) {
                [self dismissViewControllerAnimated:YES completion:nil];
            }
        }];
    }
}

Summary

This chapter explained how to create a user interface (UI) to let a user sign up for an account with an e-mail and password. It also covered how to develop a better user experience while developing the UI. In the end, signing a user up with Parse is just an API method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.249.220