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
Showing Pictures on the Wall
Open WallPicturesViewController.swift. This view will show all of your users uploaded pictures.
When the view loads, it calls getWallImages() to retrieve all the objects. As you can see, it’s empty now.
Before you can make that work, you’ll need to add some code to place the images on the wall once you’ve retrieved them. To that end, add loadWallViews(_:) as follows:
func loadWallViews(objects: [WallPost]) {
cleanWall()
var originY: CGFloat = 0
for wallPost in objects {
//1
let wallView = UIView(frame: CGRect(x: 0, y: originY,
width: self.wallScroll.frame.size.width, height: 270))
//2
wallPost.image.getDataInBackgroundWithBlock { data, error in
if let data = data, image = UIImage(data: data) {
//3
//Add the image
let imageView = UIImageView(image: image)
imageView.frame = CGRect(x: 10, y: 10, width: wallView.frame.size.width - 20, height: 200)
imageView.contentMode = UIViewContentMode.ScaleAspectFit
wallView.addSubview(imageView)
//4
//Add the info label (User and creation date)
let creationDate = wallPost.createdAt
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "HH:mm dd/MM yyyy"
let infoLabel = UILabel(frame: CGRect(x: 10, y: 220, width: 0, height: 0))
let dateString = dateFormatter.stringFromDate(creationDate!)
if let username = wallPost.user.username {
infoLabel.text = "Uploaded by: \(username), \(dateString)"
} else {
infoLabel.text = "Uploaded by anonymous: , \(dateString)"
}
infoLabel.text = "Uploaded by: \(wallPost.user.username), \(dateString)"
infoLabel.font = UIFont(name: "HelveticaNeue", size: 12)
infoLabel.textColor = UIColor.whiteColor()
infoLabel.backgroundColor = UIColor.clearColor()
infoLabel.sizeToFit()
wallView.addSubview(infoLabel)
//5
//Add the comment label (User and creation date)
let commentLabel = UILabel(frame: CGRect(x: 10, y: CGRectGetMaxY(infoLabel.frame)+5, width:0, height: 0))
commentLabel.text = wallPost.comment
commentLabel.font = UIFont(name: "HelveticaNeue", size: 16)
commentLabel.textColor = UIColor.whiteColor()
commentLabel.backgroundColor = UIColor.clearColor()
commentLabel.sizeToFit()
wallView.addSubview(commentLabel)
}
}
//6
wallScroll.addSubview(wallView)
originY += 270
}
//7
wallScroll.contentSize.height = CGFloat(originY)
}
The first step is to clean the scroll view of any other UIView objects that may be there, for example, if you reload the screen. Then you use fast enumeration to go through the whole array of objects. For every object in the array:
- Create a view to display the image and post details.
- Download the image data.
- Add the image view to the wall view
- Get the user that uploaded the image, and put it in a label with the creation date.
- Add a label with the comment.
- Add it to the scroll view and increment the next post’s position.
- Set the ScrollView’s content size.
Now, replace the content of getWallImages() with the following code:
func getWallImages() {
//1
let query = WallPost.query()!
query.findObjectsInBackgroundWithBlock { objects, error in
if error == nil {
//2
if let objects = objects as? [WallPost] {
self.loadWallViews(objects)
}
} else if let error = error {
//3
self.showErrorView(error)
}
}
}
Here’s what this code is doing:
- Create a simple query to retrieve
WallPostobjects, and sorts the query by creation date as we defined earlier in WallPost.swift. - Find the object that matches the query. In this case, show all the objects of the type
WallPost. If everything went fine, load the posts to the wall. - If there was an error, then inform the user.
Build and run! You should see the image and the comment you previously uploaded. Take some time now to play with the app, uploading some more images and comments, and seeing them appear on your wall!
Feels good, doesn’t it? :]
ParseUI
As noted earlier there is another way to present the saved images. That’s the approach you will implement next.
In the previous section you presented the images in a simple UIScrollView, and calculated their sizes yourself. You may have thought that this job would be better done with a UITableView. Well, the smart people at Parse thought the same thing, so they wrote ParseUI.framework and filled it with some very handy objects to display Parse specific UI.
You’re going to focus on these three:
-
PFQueryTableViewController: This
UITableViewControllersubclass makes is as simple as it can be to execute aPFQueryand display the result in a table. -
PFTableViewCell: A
UITableViewCellsubclass to go along with thePFQueryTableViewControllerobject. -
PFImageView: This
UIImageViewsubclass manages downloading and displaying images stored on Parse’s server.
Now, open WallPicturesTableViewController.swift and change its superclass from UITableViewController to PFQueryTableViewController.
Similarly, modify WallPostTableViewCell to make it a subclass of PFTableViewCell instead of UITableViewCell. In addition change the postImage property to be of type PFImageView instead of UIImageView.
Before you add code, you need to make some changes to your storyboard. Open Main.storyboard and locate the WallTableView scene:
Open the Attributes Inspector and you’ll see you have an option to set parameters that are specific to PFQueryTableViewController:
These parameters let you choose the object type to fetch and show in the table, and also let you define the the table’s behavior by adding pull to refresh, pagination, and a loading view. When using a simple UITableView to present the results, you could even set the PFObject keys you want shown in the table, without needing to fill it in code. Under Parse Class enter WallPost.
Now go back to WallPicturesTableViewController.swift and add the following methods:
override func viewWillAppear(animated: Bool) {
loadObjects()
}
override func queryForTable() -> PFQuery {
let query = WallPost.query()
return query!
}
Every time the view appears, you want to reload the query and the table view. To specify which query to run, you override queryForTable() to return a query for a WallPost.
Finally, add the following table view delegate method to the class:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject!) -> PFTableViewCell? {
// 1
let cell = tableView.dequeueReusableCellWithIdentifier("WallPostCell", forIndexPath: indexPath) as! WallPostTableViewCell
// 2
let wallPost = object as! WallPost
// 3
cell.postImage.file = wallPost.image
cell.postImage.loadInBackground(nil) { percent in
cell.progressView.progress = Float(percent)*0.01
println("\(percent)%")
}
// 4
let creationDate = wallPost.createdAt
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "HH:mm dd/MM yyyy"
let dateString = dateFormatter.stringFromDate(creationDate!)
if let username = wallPost.user.username {
cell.createdByLabel.text = "Uploaded by: \(username), \(dateString)"
} else {
cell.createdByLabel.text = "Uploaded by anonymous: , \(dateString)"
}
cell.createdByLabel.text = "Uploaded by: \(wallPost.user.username), \(dateString)"
cell.commentLabel.text = wallPost.comment
return cell
}
This method replaces the UITableView data source method tableView(_:cellForRowAtIndexPath:) with a more suitable form. You get the returned PFObject as a parameter, without the need search it in a results array using and index path.
Let’s go over what this code does:
- Dequeue a cell from the table view, and cast it to a WallPostTableViewCell.
- Cast the given
PFObjectto a WallPost object - Download the post image using
PFImageView‘sloadInBackgroundmethod. In the completion closure you track the download’s progress. Here you fill aUIProgressBaras the image downloads. - Add the creation date, the user’s name and the comment to the cell.
Before you can run this code, there’s one last thing you need to do. Go to LoginViewController.swift, and inside logInPressed(_:) replace the segues name from scrollViewWallSegue to tableViewWallSegue. Do the same in RegisterViewController.swift.
Build and run you code, and you’ll see the wall posts presented in a table view with a nice progress bar filling up as the images are downloading.

