How to create an iOS Photo App with Syncano and SDWebImage - part 1, offline mode

Mariusz WisniewskiMariusz Wisniewski

In this tutorial, I'm going to teach you how to create a Photo App in iOS and Swift, take a selfie (or just a picture), and store it easily on Syncano!

Our app will use a device's camera to take pictures, Syncano to store them in the cloud, and SDWebImage framework to help with caching images on a disk (so the same image doesn't have to be downloaded multiple times).

Create a new XCode project

Start by creating a new empty XCode project. Open XCode and, from the file menu, select File -> New -> Project.

New XCode project

Choose Single View Application and type the product name (e.g. SelfieTaker). Make sure the app language is set to Swift and click Next. Select a folder where your project should be created and confirm with the Create button.

Run your app, either by using the run button or by using the Command-R (⌘-R) key combination.

Run XCode project

If your app starts and you can see an empty iPhone screen, that means everything has gone fine so far -- we didn't add anything to our app yet, so the screen should be empty.

Empty iPhone

Now, let’s add some functionality to it!

Add a User Interface

First, we will add a top bar to our app, and prepare it so that it can navigate between screens.

On the left menu, choose the Main.storyboard file.

Open Storyboard

By doing so, XCode will openthe UI Editor (Interface Builder). From there, look in the right side menu of UI elements and find one called Navigation Controller, then drag and drop it to our storyboard.

Add Navigation Controller

You will see two new controllers on your storyboard. Select the second one and remove it (the end result should be that you have the initial view and a new navigation view controller). Hold down the Control button and drag and drop your mouse cursor from the the Navigation View Controller to our original view.

From the contextual menu, choose rootViewController.

Add root view controller

Select the Navigation Controller again and, in its options, mark Is Initial View Controller. This tells XCode that it should start the app with this screen.

Navigation Controller by itself doesn't define any UI elements -- it's just a container for other view controllers. Connecting a root view controller to it means that it will be the base view controller shown when the app launches (so that the app will launch with Navigation View Controller as an initial view -- and it will contain the root view controller inside).

While you are still in options, make sure to also select the Top Bar style to be Opaque Navigation Bar. This will help prevent photos from being covered by the top bar (which would happen in Translucent mode).

Navigation Controller Settings

Now we need to add some UI controllers to our main view.

Drag and drop Image View onto it. Make sure it fills the whole screen and then set up the proper constraints. By setting constraints, we tell iOS how to size our view on different devices -- right now we just want our view to fill the whole screen, regardless of device size (i.e., it will be full screen on all iPhone 4, iPhone 6 Plus, and iPad devices).

Add Image View

In the right menu, change the view mode to Aspect Fit -- this way, we tell iOS how to display images in our view, if the ratio is different than the one for our screen. Feel free to play with this option and change between the different settings later on, just to see how it works.

Set to Aspect Fit

Next, we’ll add a button to our view. Find the Bar Button Item element and drag it 4 times to our top bar -- 3 on the left and 1 on the right.

Add Bar Buttons

Now, change their names and/or icons. Click on each item on the left menu and choose icons and names for them. My settings for them are:

Set up Bar Buttons

Open the Assistant Editor mode -- we need to connect our newly added buttons to the functions that will be called every time the buttons are pressed.

Add functions

Make sure the code editor opened the ViewController.swift file, as on the screen above.

Holding down the control button, drag and drop our image view to the code section. On the assistant screen, choose

Add image view to code

We have just connected ‘image view’ to our code; from now on, we will be able to manipulate it and its content not only using Interface Builder, but also by coding.

Let’s do the same for our buttons. Hold down the control button on your keyboard, click on each button item, and try to drag and drop it to the code area inside your Class. A menu will appear asking you to set up the connection between buttons and code.

Select the Action connection type, and name it:

As the Type choose UIBarButtonItem.

Add functions

Okay, we have one last thing to add to our user interface -- adding the Collection View Controller to the storyboard.

Holding down the control button, drag and drop the mouse cursor from the All Selfies button to the Collection View Controller and choose Show. By doing so, we tell XCode that when the All Selfies button is pressed, we want to show this new ‘Collection View Controller’.

Click on your Collection View and, in its settings, change the background color to white.

Set collection view background 1

Set collection view background 2

Run your project!

Now you can run your project. You should see in iPhone Simulator (or on your phone) the user interface looking exactly like we defined it, with buttons on the left not doing anything yet. If you press All Selfies it should take you to another empty screen, where later we will list all of the selfies we have taken.

Add some code

Finally, it’s time to do some real coding. :)

Choose ViewController.swift from the menu on the left, and hide the Assistant Editor if you haven't done so yet.

Start Coding

Image Picker / Camera

Copy this code, and paste it in place of the cameraPressed function.

@IBAction func cameraPressed(sender: AnyObject) {
    //UIImagePickerController is a system controller that allows browsing images or taking new ones
    let imagePicker = UIImagePickerController()
    //defines the source of images -- device's photo album, or camera
    imagePicker.sourceType = .SavedPhotosAlbum
    //checking if .Camera type is available -- it's not on iOS Simulator
    //so we don't use it there -- instead, we will see a list of photos in saved photos album
    if UIImagePickerController.isSourceTypeAvailable(.Camera) {
        //if available, change source type to Camera
        imagePicker.sourceType = .Camera
        //camera can be either .Front or .Rear
        imagePicker.cameraDevice = .Front
        //do we want to capture photos or videos
        imagePicker.cameraCaptureMode = .Photo
    //should we allow editing photos after they were taken
    imagePicker.allowsEditing = false
    //which Class will be notified when image is taken. `self` means Class you're currently in
    imagePicker.delegate = self
    //call this method to present any view controller on screen -- here, we show the image picker
    self.presentViewController(imagePicker, animated: true, completion: nil);

Comments in the code should help you understand what the code does. In short, it creates an Instance of the UIImagePickerController object, it's a controller provided by iOS, and it lets you get images either from Saved Photos or from your device's camera.

It's important to know that iOS Simulator doesn't offer the Camera as a source of images; if you choose Camera and run your app in Simulator, it will crash. That's why we first ask what sources are available, and set it to Camera only if the system tells us it can use a Camera on our device.

Add the following code at the bottom of your ViewController.swift file.

// MARK: UIImagePickerControllerDelegate
// UIImagePickerControllerDelegate and UINavigationControllerDelegate are protocols -- they define set of behaviors
// that your Class can or must implement (methods/functions in protocol can be either required or optional)
// in this Class extension we put methods defined in UIImagePickerControllerDelegate protocol
extension ViewController : UIImagePickerControllerDelegate, UINavigationControllerDelegate {  
    //this method will be called every time image picker controller finishes picking a new image (from album or camera)
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        //we get the original image
        if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
            //we add taken picture to our image -- and show it on screen doing so
            self.imageView.image = pickedImage
        //we hide image picker controller (image was taken, we don't need it anymore)
        self.dismissViewControllerAnimated(true, completion: nil)

    //called when user pressed cancel on image picker
    func imagePickerControllerDidCancel(picker: UIImagePickerController) {
        //if user pressed cancel, we want to hide image picker from the screen
        self.dismissViewControllerAnimated(true, completion: nil)

Now, take this function and replace it with the trashPressed method.

@IBAction func trashPressed(sender: AnyObject) {
    //after user pressed trash icon, we want to remove picture from the view
    self.imageView.image = nil

Run your code now and see how it works. You should be able to press the camera button, see a list of photos stored on the simulator (or, if you run on a device, you will be able to take a selfie).
After choosing an image (or taking one), it will hide the image picker and show your photo on the screen.

Setting up Collection View - UI

Add the ‘Collection View Controller’ file to your project by using File -> New -> File menu.

Select Cocoa Touch Class.

Add collection view controller

Click Next, make sure the Language is set to Swift, and click Next again. Confirm the default location for the file by clicking on the Create button.

You will get a new file with bunch of code already in it.

Go back to your storyboard, because we need to do a few more things in there.

Let XCode know which Class to use when connecting your view to your code -- in Class settings, type CollectionViewController.

Add collection view controller class

While still in Storyboard, let's modify our UI a bit.

Click on Collection View and change the sizing setting to make our images bigger.

Set cell width and height to 120, and min spacing and insets to 3.

Set collection view size

Drag and drop a new image view from UI elements into our collection view cell.

Add image view to cell

Click on the image view and set its constraints to -8 from each side -- that will make the image view fill the cell (we use -8 and not 0, because we want to get rid of any margins -- images will be spaced properly by the collection view).

Add image view constraints

Change the cell's image view settings to Mode -> Aspect Fill, so our images can take up the whole cell space.

Set up cell's image view

Go into the Assistant Editor again -- we will need to connect this image view to our cell in code.

Assistant Editor for cell

Paste the following code on top of the file, to define an empty cell Class.

class CollectionViewCell : UICollectionViewCell {


Similar to what we did for the collection view Class, now click on the collection view cell and set its Class to CollectionViewCell (the one we defined above).

Add cell's class

Set the cell's Identifier to Cell.

Add cell identifier

Now, exactly as we did before, hold down the control button and drag and drop from the image view, to our cell, in code.

Create an Outlet connection and name it imageView.

Add cell's image view outlet

Setting up the Collection View -- coding

Choose CollectionViewController.swift from the left menu and get back to coding!

Find the viewDidLoad method and remove the following line of code from it:

self.collectionView!.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)  

Because we already set up our cell in the Interface Builder, we don't need to do it in code (doing so will actually make our app crash).

Add two more Classes on top of your file.

//utility class
class Utilities {  
    class func getDeviceIdentifier() -> String {
        return UIDevice.currentDevice().identifierForVendor!.UUIDString

This is a simple utility Class that will help us get a unique device identifier. We won't use it now, but it will be useful later, when we will be sending images to Syncano.

The second Class will describe our photos.

//class defining our Photo class
class Photo {  
    var name = ""
    var deviceId = ""
    var image : UIImage?

    //custom init method -- useful for quick creation of new objects of this class
    init(name: String, image: UIImage?) { = name;
        self.image = image
        self.deviceId = Utilities.getDeviceIdentifier()

We define some properties on our Class -- its name and underlying image. We also add the init method that will allow us to easily create new objects of this Class.

Inside the CollectionViewController Class, add this line on top.

var photos : [Photo] = []  

It will act as the source of photos displayed inside the collection view. We want to display photos, so we need a photos array. Because we want to modify this list during the app’s lifetime, we define it as var (variable) and not let (constant).

Find the function numberOfSectionsInCollectionView and change its content to return 1.

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {  
    return 1

That lets iOS know that we will have only one section of photos and that our list will not be split into different sections with photos of different kinds.

Find func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int function and change its content to return

override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {  

Here, we tell iOS how many photos we want to display in a section. Because we have only one section, we want to display all photos in it -- so we return the number of photos stored in our array.

The last step here is to find the override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) function and change its content to:

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {  
    //get the cell that should be displayed
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath)

    //cast the cell to our cell class type - CollectionViewCell
    if let cell = cell as? CollectionViewCell {
        //make the cell display our image
        cell.imageView.image =[indexPath.row].image

    //return configured cell
    return cell

Here, we configure the cell we will be displaying. We get a reusable cell from our collection view.
If the cell doesn't exist yet, it will be created and returned. If the collection view has a cell that exists but is not used, the system will pass it to us, so we can reuse it.

Next, we let system know that the Class of our cell is CollectionViewCell (we have to do this to use the image view we added), and we set the image to the one stored in our photo object.

Run your app, click on everything, and test to see that we didn't break anything; it should work exactly as before.

Passing photos to collection view

Go back to the ViewController.swift file. Inside the ViewController Class, add one more function:

//this method is called, before transition defined in storyboard is performed
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {  
    //we check the name of the transition
    if let collectionViewController = segue.destinationViewController as? CollectionViewController {
        //we add a photo to the next view controller = [Photo(name: "name", image: self.imageView.image)]

This method is being called by iOS every time a new transition is made from one view to another. We have set up that kind of transition before using Interface Builder: pressing the All Selfies button takes us to the Collection View Controller. The only thing we need to do here is to pass the only photo we have to display it on the next view.

Run your project, click on the camera button, select one photo, and click on All Selfies. You should see a list with only one element on it -- the image you selected before.

That's it! The first part of your app is finished! You're able to take pictures and view them. However, to store them in the cloud -- you’ll need to wait for the next part of our tutorial.

You can find code for this part of the the app on GitHub.

If you have any questions about this app, let me know in the comments or ping me on Twitter.

If you have any Syncano questions, join our Slack community or write to us at [email protected].

Build powerful apps in half the time

Use our serverless platform to set up your backend in minutes.

Learn more

#ios #developer, #kravmaga learner, dev relations at @syncano. Smash fear, learn anything!