SkillAgentSearch skills...

FoodTrackerBackend

This tutorial teaches how to create a Kitura Swift backend for the FoodTracker iOS app tutorial from Apple. This project contains a version of the tutorial code that has been updated to use Codable rather than NSCoder.

Install / Use

/learn @IBM/FoodTrackerBackend
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Building a FoodTracker Backend with Kitura

<p align="center"> <img src="https://www.ibm.com/cloud-computing/bluemix/sites/default/files/assets/page/catalog-swift.svg" width="120" alt="Kitura Bird"> </p> <p align="center"> <a href= "http://swift-at-ibm-slack.mybluemix.net/"> <img src="http://swift-at-ibm-slack.mybluemix.net/badge.svg" alt="Slack"> </a> </p>

This tutorial teaches how to create a Kitura Swift backend for the FoodTracker iOS app tutorial from Apple. This project contains a version of the tutorial code that has been updated to use Codable rather than NSCoder.

Upon completion of this tutorial there are several next steps you can take to add further functionality to the application:

If you would like to jump straight to one of these next steps a completed version of this tutorial with instruction on starting the server and application is available on the CompletedFoodTracker branch.

Pre-Requisites:

Note: This workshop has been developed for Swift 4, Xcode 9.x and Kitura 2.x.

  1. Install the Kitura CLI:

    1. Configure the Kitura homebrew tap
      brew tap ibm-swift/kitura
    2. Install the Kitura CLI from homebrew
      brew install kitura
  2. Ensure you have CocoaPods installed

    1. Install CocoaPods: sudo gem install cocoapods
  3. Clone this project from GitHub to your machine (don't use the Download ZIP option):

    cd ~
    git clone http://github.com/IBM/FoodTrackerBackend
    cd ~/FoodTrackerBackend
    

Getting Started

Run the Food Tracker App:

The Food Tracker application is taken from the Apple tutorial for building your first iOS application. It allows you to store names, photos and ratings for "meals". The meals are then stored onto the device using NSKeyedArchiver. The following shows you how to see the application running.

  1. Change into the iOS app directory:
cd ~/FoodTrackerBackend/iOS/FoodTracker
  1. Open the Xcode Project
open FoodTracker.xcodeproj
  1. Run the project to ensure that it's working
    1. Press the Run button or use the ⌘+R key shortcut.
    2. Add a meal in the Simulator by clicking the '+' button, providing a name, selecting a photo and a rating and clicking "Save".
    3. Check that you receive a “Meals successfully saved.” message in the console

Building a Kitura Backend

The Food Tracker application stores the meal data to the local device, which means it's not possible to share the data with other users, or to build an additional web interface for the application. The following steps show you how to create a Kitura Backend to allow you to store and share the data.

1. Initialize a Kitura Server Project

  1. Create a directory for the server project
mkdir ~/FoodTrackerBackend/FoodServer
cd ~/FoodTrackerBackend/FoodServer
  1. Create a Kitura starter project
kitura init

The Kitura CLI will now create and build an starter Kitura application for you. This includes adding best-practice implementations of capabilities such as configuration, health checking and monitoring to the application for you.

More information about the project structure is available on kitura.io.

2. Create an in-memory data store for Meals

The init command has created a fully running Kitura application, but one which has no application logic. In order to use it to store the data from the FoodTracker application, you need to create a datastore in the Kitura application for the Meal data from the FoodTracker iOS application. This tutorial uses a simple in-memory dictionary to store exactly the same Meal types that are used in the FoodTracker application.

  1. Copy the Meal.swift file from the FoodTracker app to the Server
    cd ~/FoodTrackerBackend
    cp ./iOS/FoodTracker/FoodTracker/Meal.swift ./FoodServer/Sources/Application
    
  2. Regenerate the FoodServer Xcode project to link "Meal.swift".
    cd ~/FoodTrackerBackend/FoodServer
    swift package generate-xcodeproj
    
  3. Open the FoodServer project in Xcode
     open FoodServer.xcodeproj
    

Note: When you open xcode you may see the error "No such module 'Kitura'". This is an Xcode bug, it has found and linked Kitura so disregard the message.

  1. Add a dictionary to the Application.swift file to store the Meal types
    1. Open the Sources > Application > Application.swift file
    2. Add a "mealstore" inside the app class, by inserting the following code:
      private var mealStore: [String: Meal] = [:]
      
      On the line below let cloudEnv = CloudEnv()

This now provides a simple dictionary to store Meal data passed to the FoodServer from the FoodTracker app.

3. Create a REST API to allow FoodTracker to store Meals

REST APIs typically consist of a HTTP request using a verb such as POST, PUT, GET or DELETE along with a URL and an optional data payload. The server then handles the request and responds with an optional data payload.

A request to store data typically consists of a POST request with the data to be stored, which the server then handles and responds with a copy of the data that has just been stored.

  1. Register a handler for a POST request on /meals that stores the data
    Add the following into the postInit() function in the App class:
router.post("/meals", handler: storeHandler)
  1. Implement the storeHandler that receives a Meal, and returns the stored Meal
    Add the following code as a function in the App class, beneath the postInit() function:
    func storeHandler(meal: Meal, completion: (Meal?, RequestError?) -> Void ) {
        mealStore[meal.name] = meal
        completion(mealStore[meal.name], nil)
    }

As well as being able to store Meals on the FoodServer, the FoodTracker app will also need to be able to access the stored meals. A request to load all of the stored data typically consists of a GET request with no data, which the server then handles and responds with an array of the data that has just been stored.

  1. Register a handler for a GET request on /meals that loads the data
    Add the following into the postInit() function:
	router.get("/meals", handler: loadHandler)
  1. Implement the loadHandler that returns the stored Meals as an array.
    Add the following as another function in the App class:
    func loadHandler(completion: ([Meal]?, RequestError?) -> Void ) {
	    let meals: [Meal] = self.mealStore.map({ $0.value })
        completion(meals, nil)
    }

A GET request to this route will display pages of data representing the photo, which is not very human readable. To solve this, we will make a new route which only returns the meal name and rating.

  1. Register a handler for a GET request on /summary that loads the data.
    Add the following into the postInit() function:
	router.get("/summary", handler: summaryHandler)
  1. Implement the summaryHandler that returns the names and rating of the stored Meals as an array.
    Add the following as another function in the App class:
    func summaryHandler(completion: (Summary?, RequestError?) -> Void ) {
       let summary: Summary = Summary(self.mealStore)
       completion(summary, nil)
    }

4. Test the newly created REST API

  1. Run the server project in Xcode

    1. In the top left corner of Xcode you should see a small toolbox icon with the text "FoodServer-Package" next to it. Click this icon and then click "FoodServer" from the dropdown menu.
    2. Press the Run button or use the ⌘+R key shortcut.
    3. Select "Allow incoming network connections" if you are prompted.
  2. Check that some of the standard Kitura URLs are running:

    • Kitura Monitoring: http://localhost:8080/swiftmetrics-dash/
    • Kitura Health check: http://localhost:8080/health
  3. Test the GET REST API is running correctly
    There are many utilities for testing REST APIs, such as Postman. Here we'll use "curl", which is a simple command line utility:

curl -X GET \
  http://localhost:8080/meals \
  -H 'content-type: application/json'

If the GET endpoint is working correctly, this should return an array of JSON data representing the stored Meals. As no data is yet stored, this should return an empty array, ie:

[]
  1. Test the POST REST API is running correctly
    In order to test the POST API, we make a similar call, but also sending in a JSON object that matches the Meal data:
curl -X POST \
  http://localhost:8080/meals \
  -H 'content-type: application/json' \
  -d '{
    "name": "test",
    "photo": "0e430e3a",
    "rating": 1
}'

If the POST endpoint is working correctly, this should return the same JSON that was passed in, eg:

{"name":"test","photo":"0e430e3a","rating":1}
  1. Test the GET REST API is returning the stored data correctly
    In order to check that the data is being stored correctly, re-run the GET check:
curl -X GET \
  http://localhost:8080/meals \
  -H 'content-type: application/json
View on GitHub
GitHub Stars108
CategoryDevelopment
Updated5d ago
Forks36

Languages

Swift

Security Score

80/100

Audited on Mar 19, 2026

No findings