iOS

Adding a Cloud Backend for Your iOS App Using Parse – Part 2


This is the second part of the Cloud Backend tutorial. In the first part of the tutorial series, we gave you an introduction of Backend as a Service (BaaS for short) and transformed the Recipe app. Instead of storing the recipes locally, we’ve migrated the recipes to the Parse backend. The Recipe app now connects to Parse and download the recipes from the cloud.

If you’ve worked through Part 1, you should have a basic idea about the Parse SDK. In part 1, you’ve learnt how to retrieve objects from Parse. In this part, we’ll show you how to save new recipe to the Parse backend. Of course, you’ll learn how to delete the recipe, as well.

We will build on the Xcode project that you’ve done in Part 1. So if you haven’t gone through the project and exercise, it’s highly recommended to check out the first part of the series.

Let’s get started.

Parse Backend Tutorial 2

Getting Started

Before moving to the coding part, let’s have a quick look at the new features. Previously, we’ve built a Recipe app to retrieve recipes from Parse and display them using PFQueryTableViewController. In this part, we’ll add two new features:

  • Create new recipe and save it to the cloud
  • Swipe to delete existing recipe from the cloud
Save and Remove Data from Parse

Save and remove recipe to/from the Parse cloud

Designing the User Interface

The main user interface is pretty much unchanged. However, in order to let users add new recipe, we’ll add a new view controller. The “New Recipe” view controller is triggered by tapping the “+” button of the main interface. Through the new screen, user can fill in the recipe information including name, preparation time, ingredients and photo.

Storyboard New Recipe View Controller

Adding a New Recipe view controller

We’ll not show you how to build the interface as this is not the focus of this tutorial. The “New Recipe” view controller is a subclass of UITableViewController and created using static table view. You’re encouraged to build the interface but to save your time, you can download the Xcode project from here (tested on Xcode 4.6.3). Unzip it and try it out. The rest of the tutorial will be built on this code template.

Before proceeding, remember to change the application ID and client key to your own Parse IDs in the RecipeBookAppDelegate.m:

Picking Recipe Photo From Photo Library

We’ll first implement the “Add Photo” function of the New Recipe view controller. When user taps on the “Add Photo” image, the app will bring up the photo library for picking the recipe photo. The iOS SDK provides the class UIImagePickerController to capture image from camera and access the photo library. Let’s see how to bring up the media browser.

Creating a Media Browser

The KUTTypeImage definition that we’ll use later is defined in the MobileCoreServices framework. So add the framework to the Xcode project and add the following import statement at the very beginning of NewRecipeViewController.m:

Next, add the following code to create the “showPhotoLibrary:” method:

In the above code, we first configure the image picker and set the source type to UIImagePickerControllerSourceTypePhotoLibrary. This will present a media browser that provides access to all the photo albums on the device, including the camera roll. By default, the photo library includes both saved photos and videos. In this case, the Recipe app only allows user to select recipe photo from library. So we limit the media type to kUTTypeImage. The rest of the code is self explanatory.

When user taps “Add Photo”, that is the first row of the static table view, we’ll call up the “showPhotoLibrary:” method to display the media browser. Therefore, add the following code in the same implementation file:

If you run the app and try to add a new recipe, the app will show you the photos from selection. However, the app will not respond to your selection as we haven’t implemented the UIImagePickerControllerDelegate protocol.

Parse backend photo library
Tip: If you’re using the iPhone Simulator to test out the app, your photo library is probably empty. It’s very easy to add photo into the photo album. Just drag any of your photos from Finder to the Simulator. It’ll automatically display the photo in Safari. Simply tap and hold the image to save it into the photo library.

Configuring the UIImagePickerController Delegate

To respond to the user’s selection, we have to implement a delegate that conforms to UIImagePickerControllerDelegate and UINavigationControllerDelegate protocols. Obviously, the NewRecipeViewController is set as the delegate object. In the NewRecipeViewController.h, change the interface to the following:

Open the NewRecipeViewController.m and add the following code:

When user selects a photo from the album, the didFinishPickingMediaWithInfo method of the delegate is called and passed an NSDictionary object containing the media (image or video) and associated data. With editing disabled, we can obtain the selected image from the info dictionary by using the UIImagePickerControllerOriginalImage key. The selected image is then assigned to the image view of the new recipe.

Tip: If editing is allowed, you can obtain the edited image by using the UIImagePickerControllerEditedImage key.

If you run the app again, you should be able to select the recipe photo.

Parse Backend Tutorial Select Image

Handling Text Field

If you’re using the source code template, we’ve pre-built the text fields and associate them with the code for you. The text fields are used for collecting recipe information including recipe name, preparation time and ingredients from user. The ingredients field takes in a comma-delimited string with each ingredient separated by comma. To keep the demo app simple, there is no validation for the input.

We also implemented the UITextFieldDelegate in the project template. The UITextField object messages the appropriate UITextFieldDelegate method when certain events occur. In our case, we’d like to hide the keyboard when user hits the return key. This can be easily done by implementing the textFieldShouldReturn: method, which is called when the user presses the return key on the keyboard.

Uploading Recipe to Parse Cloud

With the basic setup of the user interface, let’s move onto the core part of the tutorial. Once user hits the “Save” button, the app will call up the “save:” method and upload the new recipe including the recipe image to the Parse cloud. The Parse SDK provides an easy way to upload data. Storing data on Parse is built around the PFObject. As mentioned previously, each PFObject contains key-value pairs of JSON-compatible data.

In the “NewRecipeViewController.m”, implement the “save:” method with the following code:

To save the Recipe object to the cloud, we first create a PFObject using the “Recipe” class name. The PFObject works pretty much like the NSMutableDictionary, as you can see from the above code (line 3-8).

For the recipe image, you can easily store it by converting it to NSData and then using PFFile. Here we turn the original image into JPEG data using UIImageJPEGRepresentation. Once you configure the PFObject, you can invoke the “saveInBackground:” method to save the recipe. This method will automatically upload the image and save the recipe in background. But to better handle the upload, we use an alternative method called “saveInBackgroundWithBlock:”. You can provide additional logic that will execute after the save completes. In our demo, we will display an alert to indicate the completion, followed by notifying the main view controller to reload the recipes.

Displaying Upload Indicator with MBProgressHUB

Now you should have a better idea of how object saving works. But what are those lines of code (i.e. line 16-20) that come after the PFobject? As you know, it takes time to upload the recipe image. It’s always good to let user know something is in progress. The iOS SDK provides developers with UIActivityIndicatorView for displaying a spinner. But today let us introduce an awesome class developed by Matej Bukovinski. MBProgressHUD is an open source class that displays a translucent HUD with an indicator. You can download the class for free from Github. If you still wonder what the class does, just take a look at the following screens provided by the developer:

MBProgressHUD Samples

MBProgressHUD Samples

The MBProgressHUD class is very simple to use. Just add both MBProgressHUD.h and MBProgressHUD.m to your Xcode project, and you’re ready to go. For your convenience, we’ve bundled both classes in the project template. It only takes a few lines of code to set up the HUD. First, import the MBProgressHUD header file:

Then initialize the HUD with the current view. The MBProgressHUD class provides different HUD modes. We just use the MBProgressHUDModeInDeterminate mode and change the label to “Uploading”. The last line tells the HUD to show as it is hidden by default.

To hide the HUD, you can call the following code:

Testing the App

This is how we use MBProgressHUD while saving the recipe to the Parse cloud. Okay, it’s time to build and run the app. Try add a new recipe and save it to the Parse cloud. During the recipe upload, you should see the HUD indicating the upload is in progress. Once complete, the table view of Recipe Book view controller will refresh and load the new recipe from Parse.

Recipe App Save Recipe

Deleting Recipe from Parse Cloud

You should know how to delete a row from table view if you’ve followed the UITableView tutorial. Simply implement the “commitEditingStyle:” method with the following code:

Like saving data to the Parse cloud, PFObject provides various methods for object deletion. The “deleteInBackground:” method lets you delete the object from the cloud in background. Here we use an alternative method called “deleteInBackgroundWithBlock:” that allows to run a callback when deletion completes.

Summary

Through this tutorial series, hopefully you can see how easy it is to save data to the cloud by using the Parse SDK. If you think it’s too hard and complex to connect your app to the cloud, think again. Parse, as well as, other BaaS providers (e.g. StackMob) simplify the whole development of a backend. We hope this tutorial inspires you to add a backend for your iOS app and serves as a starting point to explore other BaaS solutions. We’re looking forward to seeing your cloud app!

For your complete reference, you can download the full source code from here. As always, leave us comment and share your thought about the tutorial. We want to hear your feedback and keep improving.

iOS
Using Text Kit to Manage Text in Your iOS Apps
Tutorial
Advanced Unit Testing in Swift Using Swinject, Quick and Nimble
SwiftUI
How To Style SwiftUI Buttons in iOS 15
  • tonym

    tonymtonym

    Author Reply

    Thank you! 😀


  • Pietro Bertini

    Thanks a lot! Great tut!

    A question: is there a way to change the “Delete” button in commitEditingStyle method. I’m building an app to make reservations. It would be great if the user could reserve a specific timetable in fact deleting the Parse object from database but the app should display something different from “Delete” maybe “Book”, or “reserve”… Any suggestion?


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      In the RecipeBookViewController, implement the following method and return the title of the delete button:

      -(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
      return @”Remove me!”;
      }


  • Podster

    PodsterPodster

    Author Reply

    Will there be an example on how to user Parse when the user is offline with the ability to sync once back online?

    Thanks for a great tutorial.


    • Yuri Ferretti

      to delete an object in the future when you can’t ensure network connectivity just send [object deleteEventually]


  • Chandler

    ChandlerChandler

    Author Reply

    How do you get the new items to load at the top instead of the bottom?


  • Sabre

    SabreSabre

    Author Reply

    When I tried to add a new recipe named in other language, not in English, to Parse cloud, then alert message showed “Upload Failure: The operation couldn’t be completed.(Parse error 122.)” Anybody can help solving this problem???


  • Mano Marks

    Mano MarksMano Marks

    Author Reply

    Great tutorials. I would love to see tutorials on:
    Core Animation
    Using the Google Maps SDK (happy to help with this one :-))


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      We’re working on a few tutorials. I’ll put Core Animation on our to-do list. We’re looking for guest writer. If you can help on the Google Maps SDK, that will be great. You can contact me via the Contact page.

      http://104.131.120.244/contact/


  • Hugh Jeremy

    It would be great if you could add to the tutorial by sending a push notification when a new data row is added to the Parse cloud.

    Thanks for all the great tutorials,
    Hugh


  • Oscar Blanco Castan

    hi anybody knows how to put search a bar?


  • Oscar

    OscarOscar

    Author Reply

    hi anyone can say me how i can put a search bar? thanks in advanced


  • Sabre

    SabreSabre

    Author Reply

    I always want give you many thanks for your great tutorials. I also understand that you are always busy and have little spare time to answer every silly question…
    But I hope you can consider that some beginners would be happy to have an answer for their own silly question.


  • Scott

    ScottScott

    Author Reply

    After saving a new recipe you get an EXC_BAD_ACCESS error after clicking on the UIAlert View.


    • Scott

      ScottScott

      Author Reply

      I forgot to add that I’m using Xcode 5 and running the iOS 7 simulator.


      • Erich

        ErichErich

        Author Reply

        I got the same EXC_BAD_ACCESS whenever I clicked ‘OK’ in the “Upload Complete” Alert-Message. Fixed it by setting the delegate there to ‘nil’ instead of ‘self’:

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”Upload Complete” message:@”Successfully saved the recipe” delegate:nil cancelButtonTitle:@”OK” otherButtonTitles:nil, nil];


        • julian_b

          julian_bjulian_b

          Author Reply

          thx for the fix… worked for me also on Xcode 5 and iOS 7


          • Zull_SHA1

            Zull_SHA1Zull_SHA1

            Author

            thanx Erich..


  • Matthew Waller

    Hi, great tutorial. Was wondering if there is a way to simply replace an array in the source code with the information on Parse. There is a lot here about displaying the array, is there any way to do a PFQuery and simply bring in new values for an array? Thanks for any help you can offer.


  • ahong222

    ahong222ahong222

    Author Reply

    I run the project download from here in xcode5,there is a problem after add a recipe object successful,there is no log,just jump to this file:”#import “RecipeBookAppDelegate.h”

    int main(int argc, char *argv[])

    {

    @autoreleasepool {

    return UIApplicationMain(argc, argv, nil, NSStringFromClass([RecipeBookAppDelegate class]));//stop here

    }

    }

    “,do you know what is the problem?


    • felix

      felixfelix

      Author Reply

      Hi any help for this? I face the same issue


  • Sebastian

    SebastianSebastian

    Author Reply

    is there any way to add the data of a geopoint (parse geopoint column) to the tablecell?


  • Scott

    ScottScott

    Author Reply

    What if the user made a mistake when saving a new recipe. How could you edit the recipe without creating a duplicate?


  • NissiVM

    NissiVMNissiVM

    Author Reply

    Hi, great tutorial! =]

    I have a question: Is it possible to have the “Load more…” in a button, instead of in a row? When you slide left the “Load more…” row the Delete button appears and when you click it an exception occurs.


    • NissiVM

      NissiVMNissiVM

      Author Reply

      This method prevents the row from be editable:

      – (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
      {
      if([self.objects count] == indexPath.row) {
      return NO;
      }else{
      return YES;
      }
      }


  • Fırat Tuncer

    After downloaded and run the finished project source code the following problem occured: I can retrieve name, ingredients, prep time but the image files. On Xcode5 iOS 7 simulator. Anyone had the same issue?


  • jetty

    jettyjetty

    Author Reply

    Hello from France! I just found your site and it is really great. Continue like that 🙂


  • Vibhoo Mishra

    I am new to Objective-c when i am running this tutorial i am getting following error message, when trying to save the things

    “Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Can’t use nil for keys or values on PFObject. Use NSNull for values.’ ”

    Please Help me ASAP


  • g2sleeper

    g2sleeperg2sleeper

    Author Reply

    When I try to import the json recipe model that is provided, I get an Error in Parse “Name must start with a letter”… can someone help me with this?


  • Joey

    JoeyJoey

    Author Reply

    Thanks for this great tutorial and I can design ios apps to add / delete record in Parse clouds now even I’m a very beginner programmer. However, do you have the sample code for update the records. I don’t know how to write the programming code to update the record.


  • John GuySmith

    how do you order the recipes alphabetically or by date created?


  • Sylvain Lanson

    hello
    this a great tutorial but i have a problem, i won’t the recent publication in up of the page not down
    thanks for your tutorial and your help
    ps: i’m french ^^


  • saad

    saadsaad

    Author Reply

    I have two problems

    The first problem:

    When top-notch data on the cloud

    The first news rises and descends to the bottom of the new news

    The second problem:

    When I want to upload the news of the new name does not accept letters of Arab

    please Help plzz …


  • steve

    stevesteve

    Author Reply

    Hi,

    How can I retrive some data to Specific Users?


  • Aaron Kalantarov

    how to export data to exel with libxl??? please help.


  • rushabh

    rushabhrushabh

    Author Reply

    How to use in swift MBProgressHUD


  • Gurjas

    GurjasGurjas

    Author Reply

    great tutorial 🙂 will recommend this site for sure 😀


  • gmmck

    gmmckgmmck

    Author Reply

    is there a swift version of this awesome tutorial?


  • سعد خالد العبدلي

    Every time to bring the data in the database in TableView , the data can scatter and do not go to the top

    For Example :
    This Image

    please Help Me Quickly


  • Nitin Nikam

    awesome tutorial…. thanks appcoda team


  • Raluca Sabou

    Your explanations are great and I really love following your tutorials. But at this moment I am having a parse problem. I fetch rows from parse into areay, and display in a tableview. The problem is that I can’t fetch more than 1000 rows ( my file has 25000 rows). Can you please suggest me a solution how i can fetch all the rows in an array? Thank you


Shares