iOS

Building an Instagram-Like App with Parse and Swift


Parse, the mobile app platform, has one particularly interesting product: Parse Core. One of its features allows app developers to store data in the cloud, without worrying about setting up servers and designing a REST API. Parse Core is also locally backed, like Core Data, which makes it a very good solution for online-offline back-ends.

This tutorial explains how to create an app that’s backed by Parse. We’ll create an Instagram-like app with these features:

  1. Load data from Parse, store it locally.
  2. Save data to Parse, write it back to the cloud.
  3. Upvote, or like, pictures of cats.

The app will be entirely created with Swift, Apple’s new programming language for making iOS apps. Parse isn’t yet rewritten in Swift, so we’ll have to create a Bridging Header to work with it.

This is what you’ll learn:

  • Working with Parse, retrieving and saving data in the cloud.
  • Integrating a Swift project with Objective-C frameworks, with Cocoapods.
  • Setting up views and a custom table view cell with Interface Builder.
  • Coding an entire app with Swift, from scratch.
  • Working with Auto Layout and constraints.
  • Using gesture recognizers, optionals, conditions, closures, properties, outlets and actions.

Let’s Get Started

First, make sure you have a Parse account. You can sign up at Parse.com with your Facebook, Google+ or GitHub account, or by entering your email address.

Then, log in to Parse and go to your apps Dashboard over at https://www.parse.com/apps.

Create a new app by clicking the Create a new App button up top. Enter “Paws” as the name for our app. Then, open the new app and make sure you’re seeing the Core tab. It’ll look like the image below.

Parse Cloud

Creating The Datastore

Parse is technically just an online database. Data is stored as objects that have a name and a number of fields, like a spreadsheet. Such an object is called a class, and it functions as the blueprint of a data structure. The class we’ll be working with is called Cat.

In the Core tab, click the button Add a class. Make sure the dropdown box says Custom, and type the name of the class: Cat. Then, click Create class.

parse-create-class

Parse creates the new class for us and adds a bunch of standard fields, such as objectId, createdAt, updatedAt and ACL. Let’s add some more fields!

With the + Col button up top, add the following fields, with name and type:

  • Name: name, type: String.
  • votes, type Number.
  • url, type String.
  • cc_by, type String.

These fields will hold the basic information for our cat database.

Importing The Data

Now that we’ve got the structure set up, we can import the data! Save this file to your computer: Cat.json.

Then, back at the Core tab and our database, click the Import button up left. Select the file you just saved and upload it. Make sure the Collection Type “Custom” is selected, and rename the collection to Cat (not rs1_Cat). Then click Finish Import. Parse will notify when your import is complete, which is usually instant, so click Got it! and reload the page.

If all went well, you should now see that the database is filled with 10 cats. They all have a name, a URL, some votes and a field for the original author of the picture.

Parse Cloud

That’s all we need to do in Parse, for now. Let’s set up the Swift Xcode project.

Setting Up The Xcode Project

Open Xcode and create a new project, right from the start screen or by using menu File -> New -> Project.

Pick from category iOS -> Application the template Single View Application. In the next screen, input the following fields:

  • Product Name: Paws
  • Organization Name: Anything
  • Organization Identifier: Anything, like com.appcoda
  • Language: Swift
  • Devices: Universal
  • Use Core Data must be unchecked

Click Next and pick a folder for your project, then click Create.

We’re not going to use Storyboards, so open the Project settings by clicking the thick bar up left that says Paws, 2 targets, iOS SDK. In the list on the left, click Paws under Target and then locate the Main Interface setting in the main area of the screen. Remove the text Main from the box.

rs1_xcode_2

Adding The Parse Library To Xcode With Cocoapods

Before we can use Parse in the code of the app, we have to include it as a dependency. For that we use Cocoapods, which is a package manager. Many app projects rely on third-party libraries, such as Parse, and Cocoapods is a tool that allows easy inclusion of libraries and ensures they’re up to date.

Install Cocoapods by executing the following command in Terminal. It’ll ask you to enter your Mac user password. Don’t include the $ sign. The sign simply indicates a shell command!

$ sudo gem install cocoapods

Don’t worry if there appears to be no progress for a couple of minutes, Cocoapods is just installing. When it’s finished, you should see a bunch of lines and ultimately … gems installed.

cocoapods-install

Next, create an empty file in the root of the Xcode app project directory and call the file Podfile. Open it with your favorite text editor and paste the following line in it:

pod ‘Parse’, ‘~> 1.7.1’
pod ‘ParseUI’, ‘~> 1.1.3’

The Podfile tells Cocoapods which libraries we want to use, and in this case it’s Parse version 1.7.1 and ParseUI version 1.1.3.

Now, close Xcode and use Terminal to go to the root directory of the app project. Write in Terminal cd, then look up the Paws directory in Finder and drag it to Terminal.

Next, type this on the command-line:

$ pod install

CocoaPods will look for the Podfile and attempt to install the dependencies we set. It can take a couple of minutes. The result should something like this:

cocoapods-parse-install

CocoaPods has downloaded and compiled Parse, and it’s dependencies, and added it to a new Workspace. From now on, we won’t be using the original app project, but we’ll be using the Workspace that CocoaPods created. It contains our original project and the CocoaPods project.

Important: Open the new Workspace in Xcode by using Finder to browse to the app root directory, and opening the Paws.xcworkspace in it. Verify that on the left in the Project navigator, two projects are shown: Pods and Paws.

Before we can get to coding the app, we need to create a connection between Parse and our project. Parse is written in Objective-C, and our project is written in Swift, and those two don’t mix and match without proper setting up.

Using Objective-C in Swift Project

Any Objective-C library, project or class can be used with Swift by setting up a Bridging Header. Technically, such a bridge will translate header files from Objective-C to Swift.

Create a bridging header by doing the following:

  1. Add a new file to the Paws directory by right-clicking on the Paws directory in the Paws project, then click New File….
  2. From the iOS -> Source category, pick the Objective-C File template and click Next.
  3. Name the class “Paws” (or whatever you like), then press continue to proceed and save the file. When prompted, click “Yes” to configure an Objective-C bridging header.
bridge-header

Xcode creates two new files: Paws.m and Paws-Bridging-Header.h. We do not need the Paws.m file, so you can simply delete it. In the Paws-Bridging-Header.h file and write the following code:

Whole lot of work for just setting up a coding project, right? Don’t worry, we’ll get to the fun stuff any minute now. Remember this: Parse’s saving us days of work by offering a ready to use online back-end!

Verifying That Parse Works

Go back to the Parse Dashboard, over at https://parse.com/apps. Hover over your account name top-right, then click Account, then click the App keys tab up top. You can also go to https://parse.com/account/keys directly.

The page will show you your App Keys, needed to identify the app with the Parse webservice later on. Such keys consist of a bunch of alpha-numeric characters, and should be kept private. They’re basically passwords for apps.

Next, open file AppDelegate.swift in Xcode. Locate the application didFinishLaunchingWithOptions method.

Add the following line of code to the method, make sure it’s the first line of the method. The entire method should look something like this:

Replace the … with the App Keys from Parse, respectively:

  1. First, the Application ID.
  2. Second, the Client Key.

Then, attempt to run the application:

  1. Make sure the right device is selected, by checking that up top right of the Play button a device is selected, such as your iPhone or iPhone 6.
  2. Then, hit the Play button or press Command-R.

The project should build and run without errors. Upon runtime, so when you can see the iPhone, it should have a black screen and then complain that the window is nil – that’s because we removed the MainInterface storyboard and haven’t yet replaced it.

The good news is: you’ve successfully set up your project with Parse and CocoaPods!

Creating The Table View Controller

To show the cats of the Paws app, we’ll use a table view controller. It’s a very common iOS interface element, showing individual rows of data in a vertical list. A great example is the Contacts app on iPhone: a vertical list of persons and phone numbers. In Objective-C and Swift, a table view controller manifests itself as the UITableViewController class.

Note: Unfamiliar with the term class? Think of it as a prototype, a mold you use in iron casting. You put iron into the mold, and out comes a copy. Such a copy is called an instance of that class.

Parse has a terrific counterpart called ParseUI, a collection of UI elements that are tightly integrated with Parse’s products. We’ll be using the PFQueryTableViewController class. It extends the functionality of UITableViewController with the data from Parse; a perfect fit.

Let’s start by creating a new Swift class called CatsTableViewController. In the Project navigator, right-click on the Paws directory and choose New file. Pick the Cocoa Touch Class template from iOS -> Source. Enter the following settings:

  • Class: CatsTableViewController
  • Subclass of: PFQueryTableViewController
  • Language: Swift
  • Make sure Also create XIB file is unchecked
New class for table view controller

Save the file in the Paws directory. When selecting the directory, make sure Paws is checked as a Target (down below).

The new class file opens, and you can see the basic structure: a method called viewDidLoad, a method called didReceiveMemoryWarning. Note that CatsTableViewController extends PFQueryTableViewController, it’s a subclass. The class PFQueryTableViewController in turn extends UITableViewController, so our cats table view controller will inherit all table view functionality while adding code and functionality from ParseUI.

Coding The Table View Controller

Let’s code the table view controller. First, we have to override the constructor method of our class to set a few base settings.

Add the following two methods to the top of the class, just after the first squiggly bracket { of the file.

You’ve just added 2 methods:

  • Designated initializer init, which takes two parameters: the style of the table view, and the className from Parse we want to use (that’s Cat).
  • A required initializer init, which takes one parameter: an instance of NSCoder. It’s contents is irrelevant for now, let’s just stick that it is required to implement it but unimportant to use the method constructively.

Within the first init, a couple of things happen:

  1. With the super.init() call, initialization is propagated to the superclass PFQueryTableViewController, which in turn initializes itself.
  2. Then, pullToRefreshEnabled is set to true. It’s an inherited property of PFQueryTableViewController. The special variable self refers to the current scope, thus the instance of the class.
  3. Then, we disable pagination and set the maximum number of objects in our table to 25.
  4. Finally, we store parameter className in the instance property parseClassName.

When, later on, we create an instance of the class CatsTableViewController, this constructor (or designated initializer) will get called and set up the basis of the table view controller.

Coding The Data Retrieval With queryForTable

The core of implementing a table view with Parse, by making use of PFQueryTableViewController is the method queryForTable. We’ve inherited that method when we subclassed PFQueryTableViewController and we need to override it: PFQueryTableViewController will call it when it wants to connect the table view controller to the Parse datastore. It literally queries data for the table, hence the method name queryForTable. Within the method, we can customize the retrieval.

Add this method to the CatsTableViewController class, just under the method viewDidLoad. Mind the squiggly brackets!

Let’s look at the signature of this new method:

What does it contain? It sets up the new method queryForTable, telling the compiler a couple of things:

  1. Override the superclass method with the same name (and signature), with the statement override.
  2. Declare the method with func and it’s name, queryForTable.
  3. Declare the parameters of the method between ( and ). In our case there’s no parameters.
  4. Finally write -> PFQuery, the return type of the method.

Within the method, this is what happens:

  1. Declare a new variable called query and instantiate it with a constructor method that takes a named parameter className, which gets assigned the value of self.parseClassName. In other words, when our table’s class name is Cat, a query that works with instances of Cat gets created at this point.
  2. Then, in case the query is empty, we set the cachePolicy property on the query. It’s value is constant PFCachePolicy.CacheThenNetwork, which means the query will first look in the offline cache for objects and if it doesn’t find any, it will download the objects from the online Parse datastore. When the table view is first put on screen, in our app, this if-statement is most likely to get executed once.
  3. Then, we order the queried objects by the “name” column.
  4. Finally, we return query.

Putting The Data On Screen

Almost there! Let’s write the final method of this class. It’ll put the data in the table view itself:

The signature of this method is this: override method tableView cellForRowAtIndexPath with parameters tableView, indexPath and object, returning a explicitly unwrapped PFTableViewCell instance. In other words: here’s a table view, here’s an object, here’s it’s index (row number) and now please return a usable cell view.

Then, first we declare a textual identifier for our cell. Each cell type has a different identifier. We’ll only be using one cell type, so we assign the String type value to it of “Cell”. The statement let declares a constant, as opposed to a variable.

Then, we declare an optional variable cell of type PFTableViewCell? and we attempt to dequeue it from the tableView parameter. Dequeueing is a mechanism that re-uses old table view cells to speed up the table view itself. The instance method dequeueReusableCellWithIdentifier takes one parameter, namely the identifier we set for this type of cell. The return type of the method is optional, and we cast it to type PFTableViewCell with the statement as?. Casting is basically the conversion of one type to another compatible type, in this case we cast from UITableViewCell to PFTableViewCell. Why is it optional? When there’s no cell to dequeue, this method will return nil.

Then, when cell is actually nil, we create a new cell from class PFTableViewCell. We indicate it’s cell type with an identifier, and give it a style of UITableViewCellStyle.Default.

Then, in the next if-statement we do something cool. Normally, when you work with an optional, you need to unwrap it. Before you can do it, you must check whether the optional is nil. You can’t unwrap an optional that has the possibility of being nil. In our case, we use optional binding (if-let) to verify if the optional is non-nil. If it contains a value, we make that value available as a temporary constant (pfObject).

Then, we assign object[“name”] to the text property of the textLabel. The textLabel is in fact, or obviously, the text label that’s shown in a row inside the table view. The variable object with type PFObject subclasses (inherits from) NSObject, so we can use the subscript [“…”] notation that retrieves the property of object with name “name”. Then it casts it to optional String?, because the object may or may not have a property called name and it could be nil.

Finally, we return cell.

Quick Recap of CatsTableViewController

Alright, inside the class CatsTableViewController we do 3 things:

  1. Initialize the class instance by setting a couple of basic settings.
  2. Integrating to the Parse back-end by overriding queryForTable: here’s the class we want to use, and this is our cache policy.
  3. Put the data on screen, in a row, by creating or re-using a cell and filling it.

Putting The Table View On Screen

Now, when you would run our app it wouldn’t do anything yet. We haven’t connected the CatsTableViewController with our app yet! Let’s do that.

Go back to the AppDelegate class and adjust the application didFinishLaunchingWithOptions method to reflect the following:

First, make sure you still have the right Parse Application ID and Client Key.

Then, we create a new instance of CatsTableViewController and assign it to variable tableVC. We use a initializer that only takes a parameter className (with value “Cat”), internally the initializer we wrote earlier gets called. We also give the tableVC a title, “Paws”, a property that’s available in any UIViewController (our table view inherits that class) and is used by the navigation controller later on.

Then, we change the appearance of the UINavigationBar. That class is used by the navigation controller, it’s the thick bar on top of many many apps. Setting the appearance makes sure any instance of that class adheres to some style rules, in this case the tintColor and barTintColor. They’re both set to a blueish color and are directly assigned an instance of UIColor. The navigation bar text color gets set to white, and then we set the iPhone status bar to a light theme (white, too).

Note: It’s not required, but to make the status bar color change take effect, you have to add a new row to the Info.plist file. You’ll find that in directory Supporting Files. Open the file, insert a new row (right-click menu) and either paste View controller-based status bar appearance or UIViewControllerBasedStatusBarAppearance in it. Make sure the row value is NO or false.

Then, we finally create the UINavigationController instance itself, assigning it to variable navigationVC. We initialize it with a rootViewController, the first view controller it shows: tableVC. Then, this is our view hierarchy:

UIWindow -> UINavigationController -> CatsTableViewController

So, we show a table view controller inside a navigation controller and put that into the top-level root view controller of the UIWindow of our app.

Finally, some boiler-plate code: we create a new UIWindow instance, assign it a full frame, assign the root view controller, and make it the key window of our app.

Run The App

Oh yeah! Let’s run that app by hitting Command-R or clicking the Play button top left. If all went well, your app should fire up with a basic blue table view that shows 10 cat names.

You can pull down the table view to refresh it, it’ll then download new data from Parse and reload the table view.

The foundation for the app we made allows us to enrich the app, which we’ll do in a second. Take some time to enjoy your work so far! You’ve successfully implemented Parse into a working app prototype. Awesome!

paws-text-demo

Creating A Custom UITableViewCell In Interface Builder

Alright, let’s spice up the app with a custom table view cell. We won’t be using the text-only cells any more, but replace them with image-name-votes cells. It’ll look exactly like the image at the top of this guide.

Let’s start by creating a new class, called CatsTableViewCell. Right-click on Paws in the File navigator of Xcode and choose New File…. Add a template of Cocoa Touch Class from iOS -> Source. Make sure it’s called CatsTableViewCell and subclass UITableViewCell. Then, tick the Also create XIB file so it’s checked. The language is Swift, of course. Create the file in the Paws directory.

Then, open the CatsTableViewCell.swift file and change the class definition to this:

See what we did there? The class now extends (inherits from) PFTableViewCell instead of UITableViewCell. Remember the tableView cellForRowAtIndexPath method? It returns a cell instance of type PFTableViewCell, that’s why we needed to change that.

Add the following outlets to the new CatsTableViewCell, at the first line of the class itself, right after the first squiggly bracket {.

We’ll need these 4 outlets to show 4 data points from Parse: the cat’s picture, the name of the cat, how many votes it got, and who the original author of the picture is.

Next, open CatsTableViewCell.xib from the Project navigator. It’ll open in Interface Builder, a tool inside Xcode that’s super helpful for setting up app user interfaces. It’s a scaffolding tool, it won’t create a functional app UI, but will just define it. Compared with a car radio, Interface Builder creates the radio console, and with Swift you code the wiring.

First, do the following:

  1. Click the main cell element in the Document Outline (left).
  2. Choose the Size Inspector tab (right).
  3. Change the Row Height to 350, and the Width to 320, and again the Height to 350.

The main view should now resize.

rs1_xcode_5

Now, we’ll add the 4 views:

  1. In the Object library, down-right, find the UIImageView class.
  2. Drag-and-drop the image view from the library to the cell view.
  3. Resize the image view, center it horizontally and separate it 15 points from the top, left and right edges. You can do this with the Size Inspector too, when selecting the image view. Its X and Y positions are both 15, its width and height are both 290.

Repeat the above steps with 3 new views, instances of UILabel. Align one on the left, and one on the right. Use the screenshot above as a reference. The left label is positioned (25, 317, 209, 21) as in X, Y, width and height. The right label is positioned (225, 317, 69, 21). The credit label is positioned (199, 285, 106, 21).

interface-builder-custom-cell

Next, configure all 4 views. Bring up the Attributes Inspector on the right, for each of the views, and set up the following:

  1. Image view: Mode to Aspect Fill, check Clip Subviews.
  2. Left label: Font to System Bold 17.0 and Color to Black.
  3. Right label: Font to System 14.0 and Color to Light Gray Color.
  4. Credit label: Font to System 14.0 and Color to White.

Now, let’s connect the views to the outlets. First, select the Cats Table View Cell again in the Document Outline on the left. Then, switch to the Connections Inspector tab on the right.

Now, locate the 4 outlets under Outlets in the inspector. See the empty circles? Drag from the circle right of catImageView to the image view in the cell. A blue line appears, and in the inspector the outlet gets a selection gizmo. Repeat these steps for the other 3 labels.

rs1_xcode_6

Setting Up Auto Layout Constraints For The Custom Cell

Note: You can in fact skip setting up Auto Layout Constraints, but your app won’t look as nice on different iPhone screens. If you’re unfamiliar with Auto Layout or Constraints, take the effort to learn it. Your future self will thank you for it. You may also refer to this tutorial about auto layout.

In order to make our app look great on iPhone 4, 4S, 5, 5S, 6 and 6 Plus we have to add a few rules to the UI elements in Interface Builder. Interface Builder comes with a handy feature called Auto Layout, and uses Constraints to manage view position, alignment and resizing. Auto Layout can be a bit quirky to work with, because it’s both intuitive and extremely logical. Ultimately, the tool is very effective at managing complex resizing tasks and will save you from writing custom layout code.

Technically, constraints are just rules for views. These are the rules we want our views to adhere to:

  • Image view: center horizontally, height fixed to 290 points, width flexible, but stay on a 15 point margin from the top, right and left edges of the cell.
  • Left label: flexible width, fixed height to 21 points, stay on a 25 point margin from the left of the cell (called Leading Space) and 11 points from the bottom of the cell.
  • Right label: flexible width, fixed height to 21 points, stay 25 points from the right and 11 points from the bottom of the cell.
  • Credit label: flexible width, fixed height to 21 points, stay 15 points from the right and 285 from the top (effectively fixing it to the bottom-right of the image view).

There are at least 4 ways to set up Constraints, we’ll be using the easiest: with the Editor menu up top.

To configure the image view, select it and then choose the following menu options:

  1. Editor -> Align -> Horizontal Center In Container
  2. Editor -> Pin -> Height
  3. Editor -> Pin -> Leading Space To Superview
  4. Editor -> Pin -> Trailing Space To Superview
  5. Editor -> Pin -> Top Space To SuperView

Then, set up the left label:

  1. Editor -> Pin -> Height
  2. Editor -> Pin -> Leading Space To Superview
  3. Editor -> Pin -> Bottom Space To Superview

Then, set up the right label:

  1. Editor -> Pin -> Height
  2. Editor -> Pin -> Trailing Space To Superview
  3. Editor -> Pin -> Bottom Space To Superview

Then, set up the credit label:

  1. Editor -> Pin -> Height
  2. Editor -> Pin -> Trailing Space To Superview
  3. Editor -> Pin -> Bottom Space To Superview

Do you see that we just stick the views to the edges, and fix them to a few positions? Your screen now should resemble the screenshot below.

rs1_xcode_7

Using The Custom Table View Cell With Swift

Alright, let’s get back to the code again – enough interface building! Open CatsTableViewController.swift and locate the designated initializer init(style: classname:).

In that method, add the following 2 lines below self.parseClassName = className;:

The first line sets the rows to the appropriate height, and the second one disallows selection on the cells.

Then, add the following line to method viewDidLoad just above super.viewDidLoad():

That line will most likely throw an error. To alleviate it, move the following line from method tableView cellForRowAtIndexPath to the top of the class and rename the value to “CatCell”.

The class definition now looks like this snippet:

We’ve just moved the cellIdentifier constant from the local method scope to the class scope, making it available in the entire class: both in tableView cellForRowAtIndexPath and viewDidLoad.

Next, replace the contents of tableView cellForRowAtIndexPath with this code:

Compare it with the old code we used earlier. What’s the difference? It’s this:

  1. The cell type changed from PFTableViewCell to CatsTableViewCell.
  2. When the cell is nil (when it couldn’t be dequeued), a new cell gets created from the XIB we just created. We retrieve it from a collection and give ownership to the current class, then cast it to CatsTableViewCell.
  3. Then, we check if the object exists and attempt to assign it’s label text the value of column name of the Parse object, like earlier.
  4. Then, the same happens for catVotesLabel and it’s text. The column votes in Parse is not of type String but is Int, hence the cast to Int?. When votes happens to be empty, we set it to be zero. Then, with a nifty technique called string interpolation we set the label text to be … votes. Roughly the same happens for the credit label.

Finally, we return the cell. Note that it is the correct type!

Let’s run the app again. Did everything go well? No bugs, errors, crashes, smoke and/or flames? Good! But… where’s the image?

Asynchronously Downloading The Image From Parse

The image’s missing! Let’s add it. Include the code fragment below in tableView cellForRowAtIndexPath, just after the last if-statement (for the credit label) but before the return statement.

Whoah! What happens here? Well, technically we rework the Parse url column into an instance of type NSURL.

We use that to start an asynchronous NSURLConnection on the main operation queue, which downloads the image as an NSData object. When the downloading has finished, a closure gets executed. It assigns the data from the download to a UIImage, which gets assigned to the image property of catImageView.

Let’s not dive too deep here, because the intricacies of the above code is irrelevant for our app. However, note these points:

  • Using NSURLConnection is quick, but a bit hacky. When doing more complex things with internet data sources, use the excellent AFNetworking (Objective-C) or Alamofire (Swift) libraries.
  • Parse allows you to store images in the cloud, and work directly with them. It’s an integral part of ParseUI, but it doesn’t allow working with external URLs (the cat pictures are from Flickr).
  • Before starting another async connection, we first clear all the operations from the main queue. This is a bit hacky: it removes pending-and-unfinished downloads from the queue. Try removing that line and run the app, you’ll see that all the images get mixed up. The dequeue-ing mechanism doesn’t reset any pending connections when it re-uses a cell, hence the wildly image loading.

Ready? Run the app again, and see if it works.

Upping The Ante: Instagram Like Function

You got this far. Awesome! Still have some air left for the final function of our app? It isn’t finished until we add the final function: the “Instagram” Like feature: when you double-tap on a picture, a vote + 1 gets added to that cat, with a neat little cat paw animation.

First, let’s add the outlet for the paw image to the table view cell. Add the following line to the CatsTableViewCell class, right below the 4 other outlets:

Then, add a UIImageView to CatsTableViewCell.xib in Interface Builder. Remember how?

  1. Look up the UIImageView class in the Object library.
  2. Drag it from the Object library to the table view cell.

Make sure to drag it right to the center of the other image view. Adjust the new image view to be 100 points wide and 100 points high. It’s X and Y are both approximately 110 points. Then, add the following constraints, when the image view has been selected.

  1. Editor -> Pin -> Width
  2. Editor -> Pin -> Height
  3. Editor -> Pin -> Top Space To Superview
  4. Editor -> Align -> Horizontal Center In Container

As you can see, this centers the image view horizontally, fixes both width and height to 100 points and keeps it at a fixed margin from the top, effectively centering it right in the middle of the cat picture image view.

xib-custom-cell-imageview

Now, create the outlet connection by selecting the Cats Table View Cell top element from the Document Outline, then selecting the Connections Inspector tab, and drawing a blue line from the catPawIcon to the image view in the cell.

Next, download paw.zip. The file contains 3 graphic files, one image for 3 resolutions. We need to import it before we can use it.

First, unzip the file. Then, open the Images.xcassets file in Xcode. Then, right-click in the list on the left (the one that says AppIcon, LaunchImage) and click New Image Set, or use the “plus” button down-left. Rename the asset that was just created to Paw and open it.

Now, drag the just unzipped files one by one from Finder to the opened asset. Make sure the files match:

Don’t worry if you don’t see the files, they’re white after all.

xcode-image-asset

Then, go back to CatsTableViewCell.xib and select the small image view. Locate the Attributes Inspector and select the right image Paw from the dropdown list at Image. The white paw image should now show in the cell view.

rs1_xcode_8

Finally remember to connect the small image view with the catPawIcon outlet.

Now, let’s get back to coding. Open the CatsTableViewCell in Xcode. Add the following code to method awakeFromNib, right before super.awakeFromNib().

Two things happen here:

  • First, we set up a UITapGestureRecognizer, which allows us to interact with any view. In this case, we add it to the contentView, the view that holds both labels and both image views of the cell. It’s initialized with a target, self, and an action, a selector for the method onDoubleTap:. So, when a double-tap is detected, the method onDoubleTap: of self (the current class) is executed. Additionally, we set the number of taps required to 2, making it a double-tap.
  • Second, we hide the catPawIcon outlet.

Next, add the onDoubleTap method to the class, right below awakeFromNib():

Such a method is called an action, and always requires one parameter: sender with type AnyObject. In the method, the following animation code happens:

  1. First, catPawIcon is made visible by setting hidden to false.
  2. Second, its alpha (transparency) is set to 1.0, which is fully visible. This is needed for a full reset of the image state, namely, its alpha channel is zero when the animation finishes.
  3. Then, the setup of the animation is coded. A class method of UIView is used, which takes 5 parameters: the animation duration, the delay before the animation, some options, then a closure of the animatable properties, and then a closure that’s executed when the animation finishes.

Visually, this happens:

  1. Reset the view by making it visible, and setting it’s alpha channel to visible.
  2. Wait one second, a delay.
  3. Within one second, the animation duration, animate the alpha channel from 1 to 0.
  4. When that’s finished, hide the image.

The great thing about this solution is it’s ease-of-use: the code will completely manage the animation. We only have to set it’s starting state and it’s ending state, and the duration, and the animation framework will interpolate states and animation steps on its own. Technically, we use two properties: a continuous value alpha, and a boolean value hidden to manage the visibility of the paw image.

Finally, run the app and see if the new feature works. You should be able to double-tap on a cell, which briefly shows the paw icon and then fades it out.

paws-demo-animation

Did it work? Great!

Integrating The Vote Action With Parse

The only thing left to do is to take increase the votes column on the Parse Cat object by one, when a vote is cast from the double-tap action.

But how do we do that?

The object we want to change is called object of type PFObject, inside the tableView cellForRowAtIndexPath method of CatsTableViewController. We can’t access that from within the table view cell, where the double-tap action is.

We can’t move the onDoubleTap method, so we have to create a reference between the table view object and the table view cell.

In order to do that, take the following steps:

  1. In CatsTableViewCell, create a new property by writing this code just below the outlets, at the top of the class:
  2. Then, write the following code inside tableView cellForRowAtIndexPath, just below the closing squiggly bracket } of the cell == nil statement:

We’ve now created a mechanism that copies the object from cellForRowAtIndexPath into our table view cell, making the object instance available in the CatsTableViewCell class.

Then, adjust the onDoubleTap method of CatsTableViewCell. Include the code below, at the beginning of the method:

This code does the following:

  1. Check if parseObject is not nil.
  2. Attempt to get the votes from parseObject, casting it to optional Int.
  3. When votes is not nil, increase the votes variable by one with the ++ operator. It’s the same as votes = votes! + 1;.
  4. Then, assign the votes variable back to the parseObject collection with method setObject.
  5. Then, call method saveInBackground() on parseObject!. This will save the current object in the background, writing it to the Parse cloud when possible.
  6. Finally, update it’s text to reflect the new vote count.

And… that’s all there is to it! Run the app with Command-R or the Play button to verify that the new feature is working.

Is it working? Great!

Quick Recap

Here’s what you learned today:

  • Working with Parse, retrieving and saving data in the cloud.
  • Integrating a Swift project with Objective-C frameworks, with Cocoapods.
  • Setting up views and a custom table view cell with Interface Building.
  • Coding an entire app with Swift, from scratch.
  • Working with Auto Layout and constraints.
  • Using gesture recognizers, optionals, conditions, closures, properties, outlets and actions.

For your reference, you can download the entire Paws project file here. Please use Xcode 6.3 (or up) to run the project. Note that you have to change both the application key and client key in the AppDelegate.swift file. Also, keep in mind that you learn better and have greater retention when you code yourself, so don’t just copy.

What do you think about this tutorial? Please leave me comment and share your thought.

Note: This tutorial is also available in Chinese. We’re going to support other languages soon. If you want to join our translation team, please contact us.
iOS
A Beginner’s Guide to NSDate in Swift
iOS
3D Touch Introduction: Building a Digital Scale App and Quick Actions
iOS
iOS Programming 101: How To Hide Tab Bar in Navigation Interface
  • Aaron Kalantarov

    Can u please do the tutorial in objective c?


    • Paul Flahan

      I agree, I still need tutorials in Objective C.


    • Reinder de Vries

      Good point, I agree. Fortunately, there’s a fine Parse tutorial available here on AppCoda: http://104.131.120.244/ios-programming-app-backend-parse/

      It’d be good exercise to create the same “Paws” app, but then in Objective-C. When using the same CocoaPods library (it’s ObjC, after all) the methods, delegates, objects etc. are identical.


    • Tareyev Gregory

      Absolutely agree. Objective-c tutorial would be great!
      P.S: Very nice tutorial, keep it up!


      • Reinder de Vries

        Thanks! How did the AppCoda tutorial on Parse/ObjC go?


        • Tareyev Gregory

          They are really great and helpful for me!
          So, creating instagram-like (or sth popular) is much more cooler, You know!
          Anyway, thanks for what You do.


    • Aaron Kalantarov

      If somebody can post the “vote” and the “nsurl” code in objective c it’s enough for me.


      • EgemenOkur

        EgemenOkurEgemenOkur

        Author Reply

        hey , I’m searching for it too . could you find anything and if , could you copy paste the code snippet please ?


      • Hales♡

        Hales♡Hales♡

        Author Reply

        Same here!


  • Mark Ramrattan

    What an incredible tutorial. Thank you for taking the time out to do this in Swift.


    • Reinder de Vries

      Thanks Mark! I’m glad you like it.


      • Ed

        EdEd

        Author Reply

        Hey,

        What do you do you if you want to add images manually and have created a file column in your Class?
        What is the replacement for the NSURL part ?


  • Joel Schirmer

    how do I fix this error [!] No `Podfile’ found in the project directory.?


  • Chris Kong

    Chris KongChris Kong

    Author Reply

    I couldn’t install the podfiles because I had to update the Cocoapods. Got some problem updating, so I ended up uninstall and tried to reinstall the lastest Cocoapods. I got this error:

    ERROR: While executing gem … (Gem::RemoteFetcher::FetchError)

    Errno::ECONNRESET: Connection reset by peer – SSL_connect (https://rubygems.org/quick/Marshal.4.8/cocoapods-0.36.4.gemspec.rz)

    Tried to look for solution, but to no avail. Anyone with this issue?


  • Bruce Elliott

    After doing the “Putting the TableView on Screen” section, I tried to run the app but no content shows in the cells. I get an empty table. No errors in Xcode. Anyone else get this same issue?


    • Mark Ramrattan

      Worked for me. I see your running simulator, did you click yes to allow incoming connections?

      Also in your database on Parse, when you uploaded the json file, did you rename it to ‘Cat’.

      Also double check your Parse ID and ClientKey are the right ones.


      • dappz

        dappzdappz

        Author Reply

        I’m still stuck here, I’ve double checked my keys and all looks well. I had also renamed the imported json file to Cat.json :s


      • Shelby

        ShelbyShelby

        Author Reply

        I’m having the same issue, not showing the names of the ‘cats’, how do make sure I’m allowing incoming connections? I’m unsure where this is? I’m running on IOS Simulator any help would be fantastic 🙂 thank you!


    • Bruce Elliott

      Double check to see if you used the right client key and credentials from parse. I had the same error.


    • Rodrigo

      RodrigoRodrigo

      Author Reply

      Verify your name class on parse, i’m had the same error and my class name on parse it’s wrong. M’let name the class on name the file.json ;(, but now its working… Delete and import again the file and change the name.


  • Vincent

    VincentVincent

    Author Reply

    Cannot invoke ‘init’ with an argument list of type ‘(@lvalue NSURLRequest, queue: NSOperationQueue, completionHandler: (NSURLResponse!, NSData!, NSError!) -> Void)’

    What’s wrong I did


    • Mark Ramrattan

      What stage did you get this error? Did cocoa pods and the bridge work correctly?


      • Vincent

        VincentVincent

        Author Reply

        When I pratice”Asynchronously Downloading The Image From Parse”,and “NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: { (response:NSURLResponse!, imageData:NSData!, error:NSError!) -> Void in

        cell?.catImageView?.image = UIImage(data: imageData)”
        thanks guy


        • Mark Ramrattan

          Are you sure the code is in the right place? That should be in ‘CatsTableViewController’ before ‘if credit’ – I’ve attached how mine is organised (which works).


          • Vincent

            VincentVincent

            Author

            Hi,Mark,error occurs,I’ve attached my works.


          • Mark Ramrattan

            What is the full error message? NSURLReq…

            Swift’s error messages often do not explain what is wrong with the code but just what confused the Swift compiler. Lets see what has confused the compiler.


          • Vincent

            VincentVincent

            Author

            Sorry,that’s is really my fault,after update my Xcode,success compile, thanks man


          • Reinder de Vries

            Just to be sure: are you on Xcode 6.3 and Swift 1.2?


          • Vincent

            VincentVincent

            Author

            thanks man, You’r right!


          • Cyrus

            CyrusCyrus

            Author

            In xcode 7, handler syntax changed.below code will fix your problem.

            completionHandler: {(response:NSURLResponse?, imageData:NSData?, error:NSError?) -> Void in

            cell?.catImageView?.image = UIImage(data: imageData!)


  • Boomslam

    BoomslamBoomslam

    Author Reply

    Thank for great tutorial 🙂


  • Damian Esteban

    Very good tutorial, however I’m having an issue when I add the code for the async image download (you’ll notice I changed some of the names, but this is the only part I’m having trouble with)

    Any help would be appreciated


  • Yosuke Nakayama

    thank you for uploaded good tutorial,

    I tried to make this one but there is error to run the app.
    ld: library not found for -lPods-Bolts
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    sample data also occured this error,
    Would you give me a advice?
    I googled but couldnt find the answer..,

    I dropped the version, but it didnt work.


    • Mark Ramrattan

      When you install Bolts via cocoa pods, make sure Xcode is closed (doesn’t install properly when its open).


  • Darshan Thakker

    Article consist all helpful information for making an app.


  • saneprofessor

    Hi, you really don’t need Parse these days. You can do the entire project using CloudKit.


    • Reinder de Vries

      That’s up to the developer. You could create the same project with Core Data, Realm, SQLite3 etc. Parse is an incredibly easy way to do local storage and cloud storage without translating between the two.


  • culture2010

    I can’t run the project on simulator. it shows only iOS device.


  • Luke Flores

    Good explanation for making app.


  • Shaun Viguerie

    Amazing tutorial! Thank you for taking the time to put this together!


  • Ceelie Lo

    Ceelie LoCeelie Lo

    Author Reply

    Thanks for the tutorial! It is great to see one that covers Swift and Parse. I’m coming across an issue in the function calling cellForRowAtIndexPath. I keep seeing a compiler error, indicating “invalid character in source file,” for the “cell = NSBundle.mainBundle()…” line. I’m a complete newbie and I’m not sure what’s going on here.


    • Reinder de Vries

      That sounds like a file encoding issue. Can you remove the line and retype it without copying it from the site?


  • BishanRuf

    BishanRufBishanRuf

    Author Reply

    Great Tutorial ! Thank you for sharing such a helpful tutorial.


  • Exia

    ExiaExia

    Author Reply

    Tried to integrate this with this: http://104.131.120.244/sidebar-menu-swift/ but I am having issues. At runtime, my navigation controller title/bar button items disappear completely, though the navigation bar is there.


  • MarkusDisqus

    Hi I seem to be having a problem installing the pod file…

    This is what I have in terminal
    (shows pod file is there)
    ML-iMac:Paws myname$ ls
    AppDelegate.swift Images.xcassets Podfile.txt
    Base.lproj Info.plist ViewController.swift

    (installing does not find it)
    ML-iMac:Paws myname$ pod install
    [!] No `Podfile’ found in the project directory.

    Here’s the Podfile as a .txt…
    pod ‘Parse’, ‘~> 1.7.1’
    pod ‘ParseUI’, ‘~> 1.1.3’

    any ideas? Gratefully received…


    • Reinder de Vries

      The Podfile has no extension, it’s just called “Podfile”, so not “Podfile.txt”. Change the file, try again and let me know whether it worked!


      • MarkusDisqus

        Thx for coming back. I did actually try this before I posted. File was created in textEdit and extension removed… Can’t work out where I have gone wrong 🙁

        Looks like a great tutorial would live to get it done.


        • Reinder de Vries

          Remove the file from the directory, and also delete the reference in the Xcode project. Then, create the file through Xcode. Right-click on the “Paws” folder in the Project Navigator, then choose New File. Pick the iOS -> Other -> File template, call it Podfile without extension, then paste the podfile contents in there.

          Check to be sure: in Terminal, are you in the right directory? You can do that with:

          $ ls -lahs


          • Nahuel

            NahuelNahuel

            Author

            Thanks Reinder de Vries! I had a similar problem and i could fix it by following your instructions


  • Phil Ondrejack

    When double tapping, the UI does not update the vote count. The MasterViewController is controlling the display and updating of the UI. What is the way to increment the vote once that function is executed. I’ve been playing around with it for awhile to no avail.


    • Cathal

      CathalCathal

      Author Reply

      cell?.parseObject = object

      should be placed inside this:

      if let pfObject = object {

      }


  • Phil Ondrejack

    Also, if I check the Parse dashboard no objects are being updated on a double tap.


    • Phil Ondrejack

      I’m getting a “nil” return on the PFObject in the CatsTableViewCell so that if-statement in the “onDoubleTap” isn’t getting executed. The image animation works just fine but it’s obviously not hitting the API on a double tap.


    • Phil Ondrejack

      I feel dumb. After a few annoyed hours, this is what I was missing…
      cell?.parseObject = object


  • Hadevs

    HadevsHadevs

    Author Reply

    Can u make another post for Instagram-Like App with Storyboard?


  • Tamara

    TamaraTamara

    Author Reply

    Hi, excellent tutorial. I’m getting a lot of errors in my PawsViewController (subclass of PFQueryTableViewController) and it keeps saying ‘Duplicate Interface Declaration’. The only way I can fix it is by deleting the class. Do you know what can help?


    • Reinder de Vries

      Did you accidentally include the class somewhere else in your code?


  • jsaffdas

    jsaffdasjsaffdas

    Author Reply

    gghfasd


  • Cynthia Cheung ✈️

    Awesome tutorial! Had no previous Swift experience and completed with some comment / google searches (minor hiccups). Look forward to more 🙂


  • csvi

    csvicsvi

    Author Reply

    Really fantastic tutorial! You did an awesome job of breaking this up into separate modules – I feel like I learned a ton that I can apply to other projects. Thanks much!


  • Danubio

    DanubioDanubio

    Author Reply

    Hello.
    I keep getting this error when trying to pod install

    /Library/Ruby/Gems/2.0.0/gems/cocoapods-0.37.1/lib/cocoapods/user_interface/error_report.rb:13:in `report’: incompatible character encodings: UTF-8 and ASCII-8BIT (Encoding::CompatibilityError)

    I have my “Podfile” within the Paws directory with no extension. can someone fill me into what I’m doing wrong.

    Thanks


  • Nate Bendall

    Hello. I keep getting this error when trying to complete the PodFile install in Terminal…

    Nates-Comp:Paws.xcodeproj utahstatenate$ cd/Users/utahstatenate/Desktop/Developer/Paws/Paws/Paws.xcodeproj

    -bash: cd/Users/utahstatenate/Desktop/Developer/Paws/Paws/Paws.xcodeproj: No such file or directory

    Nates-Comp:Paws.xcodeproj utahstatenate$ cd /Users/utahstatenate/Desktop/Developer/Paws/Paws/Paws.xcodeproj

    Nates-Comp:Paws.xcodeproj utahstatenate$ pod install

    [!] No `Podfile’ found in the project directory.

    I have double-checked my work up to this point and am using “TextWrangler” to work with xcode and have saved that file as PodFile. Can someone help me out?

    Thanks.


  • Nate Bendall

    Hello. I keep getting this error when I’m trying to install the podfile on terminal…Please advise.

    Nates-Comp:Paws.xcodeproj utahstatenate$ cd/Users/utahstatenate/Desktop/Developer/Paws/Paws/Paws.xcodeproj $ pod instal

    -bash: cd/Users/utahstatenate/Desktop/Developer/Paws/Paws/Paws.xcodeproj: No such file or directory

    Nates-Comp:Paws.xcodeproj utahstatenate$ cd/Users/utahstatenate/Desktop/Developer/Paws/Paws/Paws.xcodeproj $ pod install

    -bash: cd/Users/utahstatenate/Desktop/Developer/Paws/Paws/Paws.xcodeproj: No such file or directory

    Nates-Comp:Paws.xcodeproj utahstatenate$ pod install

    [!] No `Podfile’ found in the project directory.

    Nates-Comp:Paws.xcodeproj utahstatenate$

    Am I doing this right?

    Thanks!


  • mint_cloud

    mint_cloudmint_cloud

    Author Reply

    Thanks a lot for this amazing tutorial! I’ve added a little node.js program that refreshes the images in Parse. The urls are taken from google through googleapis, and the query changes every 15 minutes (taking random sentences from the first 7 chapters of 50 Shades of Grey!)


  • Eric M. Seitz

    ‘Parse.Type’ does not have a member named ‘setApplicationID’.

    Has anyone else run into this error, after setting the application and client keys in the AppDelegate file? I discovered some SO posts mentioning this being a problem with not yet declaring enableLocalDatastore(), I played with that but it didn’t help. Any ideas or guidance? Thank you.


    • Eric M. Seitz

      Fixed! After all kinds of googling and SO review, I took a break, shutting down xCode. I just fired up the app again and it is now working. Can’t explain it, but happy to move on.


  • Eric M. Seitz

    Run the App – at this point in the tutorial, after building the CatsTableView, my app runs successfully, but I do not understand where the cat names are coming from, within Parse. Are we hooking into your existing app db?


  • mrdaco

    mrdacomrdaco

    Author Reply

    Great tutorial,
    Trying to have some add-ons, and have to use UITableViewController. PFQueryTableViewController is a subclass of it, and needed to ‘objects’ members.

    Is there a way to use both UITableViewController and PFQueryTableViewController ?
    I did read some interesting thread about View Controller Containment, but it was in Objective-C and I cannot figure out how to do it in Swift, any suggestions ?

    Thanks


  • Dominik Prokop

    Hey ~ I’m having a problem with data loading after app launch. Basically I need to pull down the table view in order to get any data. Do you have any idea why this happens?


  • Alex Van

    Alex VanAlex Van

    Author Reply

    after adding the code:

    “cell?.catImageView?.image = nil
    if var urlString:String? = pfObject[“url”] as? String {
    var url:NSURL? = NSURL(string: urlString!)
    if var url:NSURL? = NSURL(string: urlString!) {
    var error:NSError?
    var request:NSURLRequest = NSURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 5.0)
    NSOperationQueue.mainQueue().cancelAllOperations()
    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {
    (response:NSURLResponse!, imageData:NSData!, error:NSError!) -> Void in
    cell?.catImageView?.image = UIImage(data: imageData)
    })
    }
    }”

    I keep getting error:

    “fatal error: unexpectedly found nil while unwrapping an Optional value”

    and images don’t display.

    could you please advise?


  • Alex Van

    Alex VanAlex Van

    Author Reply

    is there a reason the main storyboard wasn’t used here? doesn’t that make our life infinitely more difficult?


  • Mario Subotić

    Hi,

    I really like this tutorial! I really learned a lot. I’m trying to build on top of the project now, add new features etc… I’m having issues with everything being set up in code. I’m used working with main.storyboard. I’ve been trying to recreate the tutorial by building my own scenes but I just can’t figure out how. I’m still somewhat new to xcode and swift so if anyone could help me I would be truly grateful. If anyone had the same wish as me and managed to do it could you please share how you did it?

    Thank you!


  • Jackson Blackhurst

    Hello, So I finished this tutorial and everything works great but I have a big question. I want to add a storyboard with a slide out menu to this app. I am not that good of a coder but I would love to learn. If anyone would be willing to help that would be great. Thank You in advance!


  • Paras

    ParasParas

    Author Reply

    How would I make it so users can comment on the post


  • Farzam

    FarzamFarzam

    Author Reply

    hi. when i get to the point that app has to show the name of the cats, instead it shows the votes. what have i done wrong? please help. thanks


  • Guan Wang

    Guan WangGuan Wang

    Author Reply

    Great article! But how could I upload my picture takes by the app to Parse and show the picture in the app? Is there any article about this topic?
    Thanks!


    • Andrea

      AndreaAndrea

      Author Reply

      Did you find out how to to this?


  • Nate glass

    Nate glassNate glass

    Author Reply

    This is a great Tutorial! One complaint is that I want to use the Storyboard, and ran into a lot of errors trying to do that.


  • Kévin Empociello

    I have not started yet but this tutoriel seems to be very nice thanks !


  • CSA USC

    CSA USCCSA USC

    Author Reply

    Hi Reinder de Vries, Thank you for the amazing Swift tutorial. It is very needed in today’s time while alot people are learning Swift as a new language. I have a question though: if we were to use Storyboard instead of Nib file to build this project, will there be any difference in the code? Thank you !


  • Julien Sanfilippo

    works fine until the loading of image the code : cell?.catImageView?.image = nil
    if var urlString:String? = pfObject[“url”] as? String {
    var url:NSURL? = NSURL(string: urlString!)

    if var url:NSURL? = NSURL(string: urlString!) {
    var error:NSError?
    var request:NSURLRequest = NSURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 5.0)

    NSOperationQueue.mainQueue().cancelAllOperations()

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {
    (response:NSURLResponse!, imageData:NSData!, error:NSError!) -> Void in

    cell?.catImageView?.image = UIImage(data: imageData)

    })
    }
    }

    doesn’t work for me . i have this error on the last line :

    Value of optional type ‘()?’ not unwrapped; did you mean to use ‘!’ or ‘?’?

    i also have the same error on the final project donwload at the end of the tutorial (OSX 10,11,1 , Xcode 7,0,1) if some fixed it please let me know


    • John Michael Biddulph

      is there a fix for this?


      • Daryl Ong

        Daryl OngDaryl Ong

        Author Reply

        cell?.catImageView?.image = nil

        if var urlString:String? = pfObject[“url”] as? String {

        var url:NSURL? = NSURL(string: urlString!)

        if var url:NSURL? = NSURL(string: urlString!) {

        var error:NSError?

        var request:NSURLRequest = NSURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 5.0)

        NSOperationQueue.mainQueue().cancelAllOperations()

        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {

        (response:NSURLResponse?, imageData:NSData?, error:NSError? ) -> Void in

        (cell?.catImageView?.image = UIImage(data: imageData!))!

        })

        }

        }


  • abderblog

    abderblogabderblog

    Author Reply

    An excellent tutorial! This is the first time for me using Swift with Parse. Keep it up. Thanks…


  • gopi

    gopigopi

    Author Reply

    hi i uploaded json file as instructed. but while i am uploading in import data i get error file cannot be empty but i selected cat.json from where i downloaded. Please clarify i am confused


  • James Cooper

    Any tutorial available on creating an app like Instagram including the possibility of accessing that app from desktop as well?


  • John Michael Biddulph

    works fine until the loading of image the code : cell?.catImageView?.image = nil
    if var urlString:String? = pfObject[“url”] as? String {
    var url:NSURL? = NSURL(string: urlString!)

    if var url:NSURL? = NSURL(string: urlString!) {
    var error:NSError?
    var request:NSURLRequest = NSURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 5.0)

    NSOperationQueue.mainQueue().cancelAllOperations()

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {
    (response:NSURLResponse!, imageData:NSData!, error:NSError!) -> Void in

    cell?.catImageView?.image = UIImage(data: imageData)

    })
    }
    }

    Please help??!

    I also get:

    “fatal error: unexpectedly found nil while unwrapping an Optional value”

    and images don’t display.


  • Akhmed

    AkhmedAkhmed

    Author Reply

    https://www.udemy.com/create-full-instagram/?couponCode=promo95

    Here is Full Video Course – How to Create FULL CLONE of Instagram with Swift and Xcode


  • Ziad Alame

    Ziad AlameZiad Alame

    Author Reply

    Do you recommend using saveInBackground instead of saveEventually? I’m building something similar however I intend to implement caching.


  • Alex

    AlexAlex

    Author Reply

    Parse.com not working anymore


  • anveshi manne

    This is Great!!! Thanks a lot


  • wdcurry

    wdcurrywdcurry

    Author Reply

    Despite being two years+ old, this is still an awesome effort, thank you. Even as an experienced xcoder, i run through such samples looking for differing ways to do things. This was a great altruistic effort.


  • Jane Brewer

    It’s working perfectly. Thanks my job get done


  • Neel

    NeelNeel

    Author Reply

    Very Informative, Thanks for all efforts


  • Nilesh Kadivar

    Thanks for the detailed article.


  • Tushar

    TusharTushar

    Author Reply

    Very informative, Thanks for sharing.


  • freya riki

    freya rikifreya riki

    Author Reply

    The way of your article presentation is very effective and very easy to understand. Share more like this.


  • digifutura

    digifuturadigifutura

    Author Reply

    Great information thanks for sharing it, Instagram is the best social media app which helps to communicate it best way http://www.digifutura.com is the best application development company in usa


Shares