This tutorial teaches how to create a Server-Side Swift backend for the FoodTracker iOS app tutorial from Apple.
For more information about Swift@IBM, visit https://developer.ibm.com/swift/
Note: This workshop has been developed for Swift 3.1 and Xcode 8.x.
Install the Swift Server Generator:
- Ensure that you have Node.js 8.0 installed:
node —v - If Node.js isn’t installed, you can download and install it:
https://nodejs.org/download/release/v8.0.0/node-v8.0.0.pkg - Install Yeoman:
npm install -g yo - Install Swift Server Generator:
npm install -g generator-swiftserver
Ensure you have CocoaPods installed
- Install CocoaPods:
sudo gem install cocoapods
Clone this project:
- Clone this project from GitHub to your machine (don't use the Download ZIP option):
cd ~
git clone https://github.com/FrenchKit/SwiftServer
mkdir ~/FoodTrackerBackend-Workshop
cp -rf ~/SwiftServer/* ~/FoodTrackerBackend-Workshop
cd ~/FoodTrackerBackend-Workshop
1. Run the Food Tracker App:
- Change into the iOS app directory:
cd ~/FoodTrackerBackend-Workshop/iOS/FoodTracker
- Open the Xcode Project
open FoodTracker.xcodeproj - Run the project to ensure that its working
- Hit the build and run button
- Add a meal in the Simulator
- Check that you receive a “Meals successfully saved.” message in the console
2. Create and run a Kitura Server to Persist data from FoodTracker
- Create a directory for the server project
mkdir ~/FoodTrackerBackend-Workshop/Server
cd ~/FoodTrackerBackend-Workshop/Server
- Run Swift Server Generator:
yo swiftserver
What's the name of your application? > FoodTrackerServer
Enter the name of the directory to contain the project: FoodTrackerServer
Select a type of project. Scaffold a starter allows you to create a Basic, Web or Backend for Frontend project (including creating REST APIs) whereas Generate a CRUD application (Create, Read, Update, Delete) is designed to do data persistence. Select a CRUD application.
Select type of project:
Scaffold a starter
❯ Generate a CRUD application
Select capabilities: (Press <space> to select, <a> to toggle all, <i> to inverse selection)
❯◉ Embedded metrics dashboard
◉ Docker files
◉ Bluemix cloud deployment
Select whether you want to access other services using a Swift server SDK that's automatically generated from a Swagger definition for that service.
Service prompts
? Would you like to generate a Swift server SDK from a Swagger file? (y/N) N
Select a datastore. For a production server you would want to persist data to a database, but for this workshop we'll use an in-memory datastore for ease of setup:
Select data store:
❯ Memory (for development purposes)
Cloudant / CouchDB
Generate boilerplate for Bluemix services:
❯◯ Auto-scaling
The Swift Server generator will now create and build an empty Kitura application for you with the characteristics you selected. As you are building a CRUD application, you now need to add a data model that it provides Create Read Update and Delete operations for.
- Add a data model to persist to the datastore
cd ~/FoodTrackerBackend-Workshop/Server/FoodTrackerServer
yo swiftserver:model
Enter the model name: ServerMeal
? Custom plural form (used to build REST URL): ServerMeals
Let's add some ServerMeal properties now.
Enter an empty property name when done.
? Enter the property name: name
? Property type: (Use arrow keys)
❯ string
number
boolean
object
array
? Required? (y/N) y
? Default? (y/N) n
? Enter the property name: photo
? Property type: (Use arrow keys)
❯ string
number
boolean
object
array
? Required? (y/N) y
? Default? (y/N) n
? Enter the property name: rating
? Property type:
string
❯ number
boolean
object
array
? Required? (y/N) y
? Default? (y/N) n
? Enter the property name:
When you get to the final Enter the property name:, just tap Enter and your new model will be generated.
This has created a full Kitura Server project that provides CRUD operations for the ServerMeal object. Additionally an iOS SDK called FoodTrackerServer_iOS_SDK.zip has automatically been created in the root directly of the project in order to make it easy to connect to the server from your application.
Click here for a detailed description of the contents of the project.
-
Open and run the server project in Xcode
- Open the project in Xcode:
open FoodTrackerServer.xcodeproj - Edit the scheme and select a Run Executable of “FoodTrackerServer”
- Make sure you are running a Swift 3.1 Toolchain in
Xcode > Toolchains - Run the project, then "Allow incoming network connections" if you are prompted.
- Open the project in Xcode:
-
Check the FoodTrackerServer URLs are running:
- Kitura Homepage: http://localhost:8080
- Kitura Monitoring: http://localhost:8080/swiftmetrics-dash/
- Kitura REST API: http://localhost:8080/explorer/
-
Test the REST API is running correctly
- From the Kitura REST API explorer select “GET /ServerMeals”
- Press the “Try it out!” button
- Check for an empty response body (“[]”) and a Response Code of 200. This tests that no meals have been saved to the server yet.
Install the iOS SDK into the FoodTracker iOS application:
In order for the FoodTracker iOS application to save the meal data to the server, calls to the server's REST APIs need to be made. This could be done using URLSession, but in order to make it easier to create the correct data objects and API calls, the generated iOS SDK provides ServerMeal and ServerMealAPI classes.
- Unzip the
FoodTrackerServer_iOS_SDK.zipfile:
cd ~/FoodTrackerBackend-Workshop
unzip ~/FoodTrackerBackend-Workshop/Server/FoodTrackerServer/FoodTrackerServer_iOS_SDK.zip
- Create a Podfile in the FoodTracker iOS application directory:
cd ~/FoodTrackerBackend-Workshop/iOS/FoodTracker/
pod init
- Edit the Podfile to use install the FoodTrackerServer SDK:
open Podfile
Under the "# Pods for FoodTracker" line add:
# Pods for FoodTracker
pod 'FoodTrackerServer_iOS_SDK', :path => ‘~/FoodTrackerBackend-Workshop/FoodTrackerServer_iOS_SDK’
- Install the iOS SDK:
pod install
Update FoodTracker to call the FoodTrackerServer:
As the iOS SDK is installed as a Pod, the FoodTracker application now needs to be updated to call the provided APIs. The FoodTracker application provided already includes that code. As a result, you only need to uncomment the code that invokes those APIs:
- If the FoodTracker iOS application is open in Xcode, close it.
- Open the FoodTracker applications Workspace (not project!):
cd ~/FoodTrackerBackend-Workshop/iOS/FoodTracker/
open FoodTracker.xcworkspace
- Edit the
FoodTracker > MealTableViewController.swiftfile:- Uncomment the import of
import FoodTrackerServer_iOS_SDK
import FoodTrackerServer_iOS_SDK- Uncomment the following at the start of the saveMeals() function:
for meal in meals { saveToServer(meal: meal) }
- Uncomment the following
saveToServer(meal:)function towards the end of the file:
private func saveToServer(meal: Meal) { ServerMealAPI.serverMealCreate(data: meal.asServerMeal()) { (returnedData, response, error) in guard error == nil else { print(error!) return } if let result = returnedData { print(result) } if let status = response?.statusCode { print("ServerMealAPI.serverMealCreate() finished with status code: \(status)") } } }
- Uncomment the following
asServerMeal()extension toMealat the end of the file:
extension Meal { func asServerMeal() -> ServerMeal { let serverMeal = ServerMeal() serverMeal.name = self.name serverMeal.photo = UIImageJPEGRepresentation(self.photo!, 0)?.base64EncodedString() serverMeal.rating = Double(self.rating) return serverMeal } }
- Uncomment the import of
- Edit the
Pods > Development Pods > FoodTrackerServer_iOS_SDK > Resources > FoodTrackerServer_iOS_SDK.plistfile to set the hostname and port for the FoodTrackerBackend server (in this case adding a port number of8080):
FoodTrackerServer_iOS_SDKHost = http://localhost:8080/api
- Update the FoodTracker applications
FoodTracker > Info.plistfile to allow loads from a server: note this step has been done already:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Run the FoodTracker app with storage to the Kitura server
- Make sure the Kitura server is still running and you have the Kitura monitoring dashboard open in your browser (http://localhost:8080/swiftmetrics-dash)
- Build and run the FoodTracker app in the iOS simulator and add or remove a Meal entry
- View the monitoring panel to see the responsiveness of the API call
- Check the data has been persisted by the Kitura server
- Go the to REST API explorer: http://localhost:8080/explorer/
- From the Kitura REST API explorer select “GET /ServerMeals”
- Press the “Try it out!” button
- Check for a response body that contains data and a Response Code of 200
Congratulations, you have successfully persisted data from an iOS app to a serverside Swift backend!
Add a Web Application to the Kitura server (bonus content, if you have time)
- Update the Kitura server application to save the received images to the local file system:
- Open the
Sources/Generated/ServerMealResource.swiftsource file that contains the REST API routes - Import Foundation:
import Foundation - Update the
handleCreate()function to add the following after thelet model = try ServerMeal(json: json)statement to save the images: note:<USER_NAME>should be substituted with your user name
let photoData = Data(base64Encoded: model.photo) let fileManager = FileManager.default let publicDirectory = "/Users/<USER_NAME>/FoodTrackerBackend-Workshop/Server/FoodTrackerServer/public/" fileManager.createFile(atPath: publicDirectory + model.name + ".jpg", contents: photoData)
- Create a
~/FoodTrackerBackend-Workshop/Server/FoodTrackerServer/public/jpeg.htmlfile containing just:<img src="Caprese Salad.jpg"> - Re-build and run the server
- Open the
Rerun the FoodTracker iOS App and view the Web App
- Run the iOS app in XCode and add or remove a Meal entry
- Visit the web application at to see the saved image:
http://localhost:8080/jpeg.html
If you have sufficient time, you can optionally try Step 2: Deploying to IBM Cloud