iOS 8.3+
Swift 1.2
Parse 1.7.2

2015/04/14 — Updated to cover Parse 1.7.2.

iOS + Swift 1.2 + parse.com / Tutorial — Users Sign Up, Sign In and securing data (Part 3 or 3)

Welcome back to part 3! Our focus for this final part in the tutorial series is on signing up and signing in users, and, securing data between users.

If you have not already read the previous episodes in this series please take 20 minutes to explore Part 1 and Part 2 before continuing.

Don’t forget. This tutorial is all about Swift and Parse. If you’re looking for an ObjectiveC introduction to Parse I’m afraid you’re still out of luck.

So that we’re all starting from the same point there is a tutorial starter project over on GitHub. Let’s start by downloading a copy and checking that the project builds — if that’s successful then Hurrah!

As before, there is a shopping list of links at the end of the article.

Project Goal

The key functional capabilities we’re aiming for are:

  • User sign up
  • User sign in
  • User sign out
  • Create new country record — secured to the current user

Like the other parts in the series — I am not going to phaff with some of the UI niceties — like shifting the textfields up as the keyboard displays. We are going to focus on ticking off the feature list.

Story Board

We’ll start in the story board. Let’s build the Sign Up and Sign In scene.

Add the following to your story board.

  • View Controller > Set “Is Initial View Controller” = true
  • Label > No text content
  • Label + Text Field for “Email address”
  • Label + Text Field for “Password”
  • Button > “Sign Up”
  • Button > “Sign In”
  • Activity Indicator

We need to create a “show” segue between this new view controller and the navigation controller. Give the segue an identifier of “signInToNavigation”

Your story board should look like this.

Sign Up and Sign In View Controller

Let’s create a controller class file for our sign up sign in view.

Add a new file to the project.

  • OS = iOS
  • Type = Cocoa Touch class
  • File name = SignUpInViewController
  • Subclass = UIViewController
  • Language = Swift

Let’s not forget to wire up the controller class to the Sign Up In view in our story board.

Important — make sure you set the Storyboard ID = SignUpInViewController. We will use this when we come to Sign Out.

Wiring up the textfields

With the assistant editor open — SignUpInViewController + Story board visible — lets create the outlets and actions for the activity indicator, buttons, text fields and the empty label.

Add the following code to your SignUpInViewController class file.

Don’t forget to DRAG from the outlet “markers” to the story board items to complete the wiring up.

We’ll set the Activity Indicator to be hidden in the viewDidLoad() method.

Sign Up

Okay so let’s create the super simple sign up workflow.

Sign up steps

  • User > Complete email address and password fields
  • User > Click Sign Up
  • User > Agree to the terms and conditions
  • Parse > Create a PFUser object
  • Parse > Send user a welcome and validation email
  • App > Sign the user in

Now being a simple tutorial I am not going to implement any kind of email address or password validation. That said, Parse will check the email address is a valid one and that we don’t already have a user with the target email address. Beyond that you’ll need to deal/handle those things yourself. The user will not be required to validate their email address before they can use the app, although you could easily implement that workflow if you needed/wanted.

Lets update the Sign Up outlet method with the code below.

The code is pretty easy to understand so I’ll not go into any detail. We create an alert and only if the Agree button is clicked do we do something. If any other button(s) are clicked then the alert is dismissed and the user remains on the Sign Up / Sign In scene. If the user clicks the Agree button then processSignUp() is called.

So let’s add the processSignUp() method.

There is a lot going on in this method so lets step through the code — we’ll pick up the action as we start to create a parse PFUser.

var user = PFUser() 
user.username = userEmailAddress
user.password = userPassword
user.email = userEmailAddress

We create a new PFUSer object. Notice that the username and email address receive the same data — this is a side effect of parse maintaining a seperate email address field.

user.signUpInBackgroundWithBlock { (succeeded: Bool, error: NSError?) -> Void in

This is one area that DID change moving from Swift 1.0 to Swift 1.2. Previously you called the “signUpInBackgroundWithBlock” using user.signUpInBackgroundWithBlock {(succeeded: Bool!, error: NSError!) -> Void in which has now changed to user.signUpInBackgroundWithBlock {(succeeded: Bool, error: NSError?) -> Void in.

We call the PFUser signUpInBackgroundWithBlock method. This is a non blocking background method, we use the activity indicator to notify the user that something is happening.

if error == nil { dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("ToTableView", sender: self) }
}

If creating the user was successful then we log them in and display the table view controller.

When a user is created the Parse backend sends a welcome email containing a validation link. Parse has many options and features to help manage and support your users, I recomend spending some time looking over the options available to you.

Our app automatically signs the user in, however it would not be difficult to adjust the workflow so that users must click the validation link in their welcome email before they are passed to the table view. The Parse user class (table) has a emailValidated (Bool) column that can be checked as part of a workflow.

self.activityIndicator.hidden = true
if let message: AnyObject = error!.userInfo!["error"] {
self.message.text = "\(message)"
}

If the user sign up failed we disable the activity indicator and display the Parse error message in the message label. The messages and error codes from Parse can be very descriptive. You might want to wrap the error message in some logic to display simpler or translated messages.

First Test

Let’s try out our handy work! We should be able to launch the app and Sign Up — if we’re successful we’ll be pushed through to the table view. Because we have no sign out feature yet, you’ll need to restart the run to test failure.

Sign In

Dealing with Sign In workflow is very similar to Sign Up.

Sign In steps

  • User > Complete email and Password fields
  • User > Click Sign In
  • Parse > Verify credentials combination
  • Parse > Return a valid PFUser object — or — error
  • App > Sign the user in

Reminder…. being a simple tutorial I am not going to implement any kind of sign in validation, like checking login attempts to stop brute force attacks. In a real world application you would definitely want to consider carefully how you deal with the Sign In (and Sign Up) features to protect your application, users and data… and business.

Lets update the Sign In outlet method with the code below.

Much of this code is very similar to the Sign Up method so I’m not going to spend too much time talking about this.

The key lines are

PFUser.logInWithUsernameInBackground(userEmailAddress, password:userPassword) { (user: PFUser?, error: NSError?) -> Void in

As with Sign Up, this is a non blocking background task that verifies the user credentials on the Parse platform and returns a PFUser object. The PFUser object is a critical object if our app has any form of user based security — more on that soon.

Extending the User object

The PFUser object can be extended with your own columns. You define and add them to the User class just like any other class, and, you get at the information in exactly the same way as any other class.

ie: user[“gender”]

Sign Out

For the Sign Out button we’ll add a button to the navigation bar, on the left. Drag a Button Bar Item into to the navigation bar and select the identifier “Stop” — that will give us an X button.

You will need to create an IBOutlet for this button within the table view controller. Copy the following code into your class file and then drag the outlet marker to the button and complete the connection.

You should find the Sign Out code self explanitory.

PFUser.logOut()

The user is signed out — this action destroys the valid PFUser object.

let storyboard = UIStoryboard(name: "Main", bundle: nil) 
let vc = storyboard.instantiateViewControllerWithIdentifier("SignInViewController") as UIViewController
self.presentViewController(vc, animated: true, completion: nil)

Finally we display the Sign Up / In view.

Second Test

We’re now in a position where we can test the app again. We can Sign Up, Sign In and Sign Out.

Add a new record

We need to add the ability for users to create their own country records. We’ll add an “+” add button to the navigation bar and create a method that ensures new records are secured to the current user.

Updating the story Board

For the +/Add button we’ll add a button to the navigation bar in the table view controller, positioned on the right.

Drag a Button Bar Item into to the navigation bar and select the identifier “Add”.

Here is the code that you need to add to the table view controller.

And let’s drag the outlet marker to the button to complete the wiring up.

We will also add an identifier to the segue, from the table view to the detail view so that we can reference it when the add button is clicked. We will call this segue “TableViewToDetailView”.

Saving new records

In order to save new records back to parse we will need to adjust our Save method within the detail view controller. Update the previous method with this code.

I have purposly kept this code simple so that it’s easy to see what’s going on — you might want to refactor out some of the code duplication. Let’s walk through the code.

if let updateObject = currentObject as PFObject? {
updateObject["nameEnglish"] = nameEnglish.text
updateObject["nameLocal"] = nameLocal.text
updateObject["capital"] = capital.text
updateObject["currencyCode"] = currencyCode.text

Check to see if we already have a currentObject. We will only have a current object if the record already exists on the parse server. If we have a record then we can go ahead and update the values.

updateObject.saveEventually()

Once the values are updated we can save the values back to the server. The saveEventually() method is a non blocking background method and is clever enough to deal with connectivity breakages — hence “eventually”.

If a currentObject was not found then we need to create a new one.

var updateObject = PFObject(className:"Countries")

Now we can update the values.

updateObject["nameEnglish"] = nameEnglish.text updateObject["nameLocal"] = nameLocal.text 
updateObject["capital"] = capital.text
updateObject["currencyCode"] = currencyCode.text

Being a new record we want to ensure that only the current user can view and edit this record. So we set the record ACL

updateObject.ACL = PFACL(user: PFUser.currentUser())

What we’re doing here is pushing the current user object into the parse row ACL, the default permission is set to read and write. It is possible to specify read and write permissions seperately, and to provide multiple user objects. It is worth reading the Parse documentation — there are lots of examples that show how you might share records between users.

Lets save the record back to the parse server.

updateObject.saveEventually()

The final part of this method returns the user to the table view controller.

self.navigationController?.popViewControllerAnimated(true)

Final test

Well done! We’re at the end of the project.

We’ve created an impressive app that:

  • Provides user sign up, sign in and sign out
  • Connects to a central data store for data
  • Secures data objects so they remain secret betgween users

Bits we’ve missed

There are some topics that I’ve not included in the tutorial that you should read up on and consider adding to your app.

  • Caching data, Parse has some clever caching capabilites that will improve app performance
  • Form validtion, you really must add validation to every place a user can type something.
  • Email configuration and validation, you will need to consider how you manage the email workflow of validating users and definitely write some nice text for the emails.
  • Passwords, you know that users will forget their passwords. Parse has a password reset capability — you just need to configure it and add the appropriate button to your app.
  • Twitter and Facebook, you can allow users to sign up using their social credentials. There are reasons why you might not want to do that, but it’s there if you need it.

There are many places you can take this project concept, just remember to consider any validation and workflow rules that you will need to cover off for your specific requirements, maybe you have legal or business or client needs to take in to account.

If you want to cheat — there is a completed tutorial project over on GitHub.

I’d love to hear your feedback and ideas this project has helped you imagine and build. Good luck for the future. Over and Out.

Links

Originally published at www.bizzi-body.com/blog on February 10, 2015.