Parse Tutorial: Getting Started with Web Backends
Get started with Parse, and learn how to set up your iOS app with a backend that lets you store user accounts, posts, and attachments! By Ron Kliffer.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Parse Tutorial: Getting Started with Web Backends
35 mins
Logging In
Open the LoginViewController.swift class, and take a look at the method below:
@IBAction func logInPressed(sender: AnyObject) {
//If user logged succesful:
performSegueWithIdentifier(scrollViewWallSegue, sender: nil)
}
As you can see, this part is very similar to the registration process! You are going to use PFUser
again, but this time you’ll be using it to log in. Replace the stubbed-out content of the above method with this code:
@IBAction func logInPressed(sender: AnyObject) {
PFUser.logInWithUsernameInBackground(userTextField.text, password: passwordTextField.text) { user, error in
if user != nil {
self.performSegueWithIdentifier(self.scrollViewWallSegue, sender: nil)
} else if let error = error {
self.showErrorView(error)
}
}
}
As you can see, the process is quite simple and very similar to the registration process. Rather than just perform the segue, you first check that the username and password match what’s in the data store.
Build and run the app and you’ll see the login view below:
Try to log in with the same user you created in the previous section. If all goes well, your app will move to the wall view. As a sanity check, try logging in with a bad username or password to see the error message.
Posting to the Wall
Both previous actions (register and log in) will move the app to the Wall View. In this view, you are going to see the pictures that all the users of your backend service uploaded, with their comments attached.
But before you can see anything, you’ll have to upload something! :]
Parse makes it easy to upload files. Open UploadImageViewController.swift, which is where you’ll do the work to upload files.
A logged-in user can tap the “Upload” button on the Wall view to take them to the upload screen shown below.
From here, the user can enter an optional comment and tap “Select Picture” to select something from the library to upload using the standard image picker.
All this is already implemented in the starter app – now it’s time to add the code that completes the implementation of sendPressed(_:)
. This is the action – linked to the “Send” button on the Navigation Toolbar – that sends your picture and comment to the server.
The process consists of two parts. First, upload the image using a PFFile object; second, attach it to a PFObject
, and upload it to the server.
As you saw earlier in the tutorial, you can add and retrieve various fields to a PFObject
using setKey
and objectForKey
. But if you have a specific type of object you use in your app, say like a wall post, wouldn’t it be nice to give it it’s own subclass with relevant properties? You will next see how you can make that happen.
Custom Parse Objects
Open the WallPost.swift file from the Model group in the project navigator. Right now, you’ll see a simple NSObject
subclass with an empty implementation. The first thing you’ll need to do is make it a PFObject
subclass as follows:
class WallPost: PFObject {
}
You also want WallPost
to conform to the PFSubclassing
protocol.
The PFSubclassing protocol declares a few required methods for subclassing a PFObject
. The PFObject+Subclass.h Obj-C category implements these methods, and you can override them.
You will do this by adding the extension shown below right after the WallPost
class. This extension contains two required protocol methods.
extension WallPost: PFSubclassing {
// Table view delegate methods here
//1
class func parseClassName() -> String {
return "WallPost"
}
//2
override class func initialize() {
var onceToken: dispatch_once_t = 0
dispatch_once(&onceToken) {
self.registerSubclass()
}
}
}
- Set the name of the class as seen in the backend database.
- Let Parse know that you intend to use this subclass for all objects with class type
WallPost
. You want to do this only once, so you’re usingdispatch_once_t
to make sure of that.
Next, add three properties to the WallPost
class, as follows:
@NSManaged var image: PFFile
@NSManaged var user: PFUser
@NSManaged var comment: String?
Here you’re adding a PFFile
property to hold the posted image, a PFUser
property to hold the user who uploaded the image, and an optional String
property for the post comment.
You’re using @NSManaged
here because deep down, PFObject
properties are just a set of key-value parameters. This way, when you set the value of each property, it will automatically be written as a key-value pair.
Another thing you want to do is define the PFQuery
object that this subclass returns when calling query()
. Add the following to the WallPost
class in WallPost.swift:
override class func query() -> PFQuery? {
//1
let query = PFQuery(className: WallPost.parseClassName())
//2
query.includeKey("user")
//3
query.orderByDescending("createdAt")
return query
}
Here’s what’s going on in this method:
- Create a
PFQuery
object for theWallPost
class. - Request that this query will return the full user details. Without this line of code, the query will just return the object reference of the user without its details.
- Sort the results by their creation date.
The last thing to do in WallPost.swift, before moving on, is writing an initializer. Add the following to the WallPost
class:
init(image: PFFile, user: PFUser, comment: String?) {
super.init()
self.image = image
self.user = user
self.comment = comment
}
override init() {
super.init()
}
This is a simple initializer to create a WallPost
object – either with starter values or without.
Now that you have the WallPost
class done, you’ll go back to uploading the images to the Parse server.
Open UploadImageViewController.swift, and right before the end of sendPressed(_:)
add the following code:
//Upload a new picture
//1
let file = PFFile(name: "image", data: pictureData)
file.saveInBackgroundWithBlock({ (succeeded, error) -> Void in
if succeeded {
//2
self.saveWallPost(file)
} else if let error = error {
//3
self.showErrorView(error)
}
}, progressBlock: { percent in
//4
println("Uploaded: \(percent)%")
})
Here’s what’s going on here:
- Create the
PFFile
object with the data of the image, and save it in the background. - If successful, save the
PostWall
object with the file you just successfully uploaded. - If not, inform the user.
- When saving a file, Parse let’s you track the progress with this progress block (closure in swift). Here you just write the progress to the console.
Next up is saveWallPost(_:)
; add the following to the WallPost
class:
func saveWallPost(file: PFFile)
{
//1
let wallPost = WallPost(image: file, user: PFUser.currentUser()!, comment: self.commentTextField.text)
//2
wallPost.saveInBackgroundWithBlock{ succeeded, error in
if succeeded {
//3
self.navigationController?.popViewControllerAnimated(true)
} else {
//4
if let errorMessage = error?.userInfo?["error"] as? String {
self.showErrorView(error!)
}
}
}
}
This method does the following steps:
- Create the
WallPost
object with the uploaded image, the current logged in user, and the comment. - Save to
WallPost
in the background. - If successful, go back to the wall.
- If not, inform the user.
Build and run your app. Log in with the user you created previously, and go to the upload screen via the top right button in the Wall Screen. Press “Select Picture” to select a picture from your gallery. When it’s selected, write a comment if you like, and press the “Send” button.
You can follow the percentage of the upload in the console – the progress block of the upload operation updates with the percentage complete status of the upload. Here, it’s shown in the debug console, but your finished app would more correctly show a progress bar to the user.
Now go to the Core Data Browser and view the object in your new table called WallPost. Hooray! But wait — you can’t see it in the app yet!
Now’s a perfect time to implement the picture retrieval process! :]