Communication is pretty fascinating. A human uses sounds, movement, symbols and analogies to encode concepts and ideas with the hopes of transferring whatever’s in their head to someone else’s. Our ability to decode messages is dependent on having a common language, similar experiences, shared knowledge. Machines and programs aren’t very different—they each have various ways of processing their environment and typically need to communicate what they know to other machines. Like us they typically need to encode messages into a shared format. Encodings could be binary or plaintext but often they need to carry semantic value so we use formats like CSV, XML, Markdown or JSON.

Lately I’ve been playing around with Google’s gRPC tools which provide a way for machines and programs to speak across language boundaries with a lot of semantic value. You model how everyone should communicate and generate code to quickly get different systems familiar with one another. Apple has recently added support for Protocol Buffers, the primary way of defining gRPC services. With some additional work we can use Apple’s new support to make a Swift client speak to a gRPC server!

Before you begin…

If you haven’t already you should do the following:

Here we go!

Create a new Swift project 🎉:

$ mkdir helloswift

$ cd helloswift

$ swift package init --type executable

Add a dependency to Package.swift:

This dependency makes it easier to use the generated protobuf file with Google’s helloworld example. Run build to pull down all the dependencies and create an Xcode project file:

$ swift build

$ swift package generate-xcodeproj

Now lets generate some code for our Swift project that will let our client communicate with the helloworld example. We’re going to copy helloworld.proto out of the helloworld example into our project, ideally you should maintain a single .proto file to use with other languages but this skirts an issue with protoc unable to find the file:

$ cp $GOPATH/src/google.golang.org/grpc/examples/helloworld/helloworld/helloworld.proto . $ protoc --swift_out=Sources/. helloworld.proto

This created helloworld.pb.swift and added it to our Sources folder. Now lets use it in our project. Since Apple’s protobuf plugin doesn’t yet support protobuf services we’ll need to write the service code by hand using the SwiftGRPC library I wrote. Here’s an example that supports the Greeter service in the helloworld.proto:

This clearly isn’t production ready code, but it does express the idea 😎

Now build and run 🚀

$ swift build && .build/debug/helloswift

You should see the output:

> Optional(Helloworld_HelloReply(message:”Hello World”))

Quick recap

This was a very quick demo defining a gRPC service in Swift using protocol buffers. The SwiftGRPC library was something thrown together over a couple weekends so it’s pretty scrappy but I’m open to feedback. I learned a lot about HTTP/2 in the process and would really love to see proper support in Swift. As interesting as gRPC is at definining how machines should communicate I found myself even more excited about the semantics behind HTTP/2. Hope this was useful 🙂