Introduction to Protocol Buffers on iOS

Protocol buffers are a language-agnostic method for serializing structured data that can be used as an alternative to XML or JSON in your iOS apps. By Vincent Ngo.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

The Backend

Within the folder Starter/Server, you’ll see the following:

  • RWServer.py manages a Python server built on top of Flask. It contains two GET requests:
    • /currentUser gets the current attendee’s information.
    • /speakers gets the list of speakers.
  • RWDict.py contains a dictionary of speakers that RWServer will read from.
  • /currentUser gets the current attendee’s information.
  • /speakers gets the list of speakers.

Now it’s time to set up the environment to run protocol buffers. In the following section, you’ll set up the required environments to run Google’s protocol buffer compiler, Swift’s Protobuf plugin, and install Flask to run your Python server.

Environment Setup

There are a several tools and libraries that you have to install before using protocol buffers. The starter project includes a script named protoInstallation.sh that handles all of this for you. Luckily for you, it will check if any of the libraries are installed before installing each one!

This script will take a while to install, especially when installing Google’s protocol buffer libraries. Open up your terminal, cd into the Starter directory and execute the following command:

$ ./protoInstallation.sh

Note: You may be prompted to enter your admin password while running the script.

When the script completes, run it again to ensure you get output similar to the following:

protocol buffers

If you see this, the script has successfully completed. If the script failed, you might have entered the wrong admin password. In that cause, try rerunning the script; it won’t reinstall anything that happened successfully.

Here’s what the script has accomplished:

  1. Installed Flask to run the Python Local Server.
  2. Built the Google protocol buffer compiler from Starter/protobuf-3.1.0.
  3. Installed the protocol buffer module for Python so the server can use the Protobuf library.
  4. Moved the Swift Protobuf plugin protoc-gen-swift into /usr/local/bin. This allows the Protobuf compiler to generate Swift structs.

Note: For more information on how the script works, you can open the protoInstallation.sh file in a text editor to see what commands are being executed. This requires some basic bash knowledge.

You now have everything you need to start using protocol buffers!

Defining a .proto File

.proto files define protocol buffer messages which describe the structure of your data. When fed through the protocol buffer compiler, they generate data accessor structs.

Note:In this tutorial, you’ll define messages with proto3, the latest protocol buffer language version. For more in-depth knowledge on syntax and how to define a proto3 file, check out Google’s guidelines.

Open ProtoSchema/contact.proto in your favorite text editor. Here the .proto file has already been defined for you to generate Contact and Speakers messages:

syntax = "proto3";

message Contact { // 1

  enum ContactType { // 2
    SPEAKER = 0;
    ATTENDANT = 1;
    VOLUNTEER = 2;
  }

  string first_name = 1; //3
  string last_name = 2;
  string twitter_name = 3;
  string email = 4;
  string github_link = 5;
  ContactType type = 6;
  string imageName = 7;
};

message Speakers { // 4
  repeated Contact contacts = 1;
};

Going over what this definition actually contains:

  1. The Contact model describes a person’s contact information. This will be displayed on their badges in the app.
  2. Every contact should be categorized so it will be easy to differentiate between guest and speakers.
  3. Every message and enum field found in a proto definition must be assigned an incremental and unique tag. These numbers are used to identify fields in the message binary format, so it’s vital to maintaining the order. For more information on tag and field management, check out reserved fields in Google’s doc.
  4. The Speakers model contains a collection of contacts. The repeated tag indicates an array of objects.

Generating Swift Structs

When you pass contact.proto into the protoc program, the messages in the proto file will generate Swift structs. These structs will conform to ProtobufMessage. protoc will provide properties for every Swift field, initializer, and methods to serialize and deserialize data.

Note: For more information about the capabilities of Swift’s protobuf API, please refer to Apple’s Protobuf API documentation.

In terminal, navigate to the Starter/ProtoSchema directory. Open protoScript.sh in a text editor and you’ll see the following:

#!/bin/bash
echo 'Running ProtoBuf Compiler to convert .proto schema to Swift'
protoc --swift_out=. contact.proto // 1
echo 'Running Protobuf Compiler to convert .proto schema to Python'
protoc -I=. --python_out=. ./contact.proto // 2

The script runs protoc twice against contact.proto — once to create the Swift source and then once again for Python.

Back in the terminal, execute the script by running the following:

$ ./protoScript.sh

You should see this output:

Running ProtoBuf Compiler to convert .proto schema to Swift
protoc-gen-swift: Generating Swift for contact.proto
Running Protobuf Compiler to convert .proto schema to Python

You’ve created Swift and Python source files from the contact.proto file.

Within the ProtoSchema directory, you should see two generated files one in Swift, and one in Python. Notice that each generated file will have a corresponding .pb.swift or .pb.py The prefix pb represents that it’s a protocol buffer generated class.

protocol buffers

Drag contact.pb.swift into Xcode’s project navigator and place it in the Protocol Buffer Objects group folder. Check “Copy items if needed” when prompted. In either Finder or Terminal, copy contact_pb2.py to the Starter/Server folder.

Feel free to look inside the contents of contact.pb.swift and contact_pb2.py to see how the proto messages map to structures in the output languages.

Now that you have your generated model objects, it’s time to integrate!

Running the Local Server

The sample project contains a prebuilt Python server. This server will provide two GET calls: one to retrieve the attendee’s badge information, and another to list the speakers.

This tutorial won’t get into the server code. However, it’s important to note that it leverages the contact_pb2.py model file you generated with the protocol buffer compiler. Feel free to take a closer look at RWServer.py if you are interested in the specifics of this, but it isn’t necessary to do this to follow along with this tutorial.

To run the server, open Terminal and navigate to Starter/Server. Now run the following command:

$ python RWServer.py

You should see the following:

protocol buffers