Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
20 Sep 2025 · 5 min read ·Article 104 / 110
Go

104. Case Study: iOS Client (Swift) with a gRPC Go Backend

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

104. Case Study: iOS Client (Swift) with a gRPC Go Backend

When building modern backend systems, communication between applications becomes absolutely critical. One of the most popular approaches today is gRPC, an RPC framework built on Protocol Buffers (Protobuf) that is efficient and delivers high performance. In this article, I’ll walk through a case study of building communication between an iOS client (using Swift) and a Go backend, using gRPC as the communication protocol.

We’ll cover the reasoning behind the chosen architecture, the practical steps involved, and share hands-on code examples. This scenario is fairly common in modern application development that prioritizes performance and maintainability.


Why gRPC?

Before diving into the case study, let’s review: Why gRPC?
In short, gRPC offers:

  • Efficiency: It uses Protobuf instead of JSON—smaller and faster.
  • Interface contract: Protobuf provides strong typing through .proto files, so the client and backend share a clear contract.
  • Multi-language support: Including Go, Swift, Java, and more.
  • Streaming: Supports real-time bidirectional streaming communication.

Let’s look at how gRPC and REST differ in certain aspects through the following table:

REST/JSONgRPC/Protobuf
SerializationText (JSON)Binary
PerformanceSlowerFaster
API contractLooseVery strict
StreamingLimitedNative
Multi-language supportFairly goodExcellent

The Case: A Simple Notes App

Imagine the scenario: we’re building a simple todo-list application.

  • Client: iOS App (Swift)
  • Backend: Go with gRPC

The app lets users perform CRUD operations (Create, Read, Update, Delete) on notes.

1. Designing the Protobuf Contract

First step: write the API contract in a Protobuf file (note.proto).

proto
 1syntax = "proto3";
 2
 3package note;
 4
 5service NoteService {
 6    rpc CreateNote (CreateNoteRequest) returns (CreateNoteResponse);
 7    rpc GetNotes (GetNotesRequest) returns (GetNotesResponse);
 8    rpc DeleteNote (DeleteNoteRequest) returns (DeleteNoteResponse);
 9}
10
11message Note {
12    string id = 1;
13    string title = 2;
14    string content = 3;
15    string created_at = 4;
16}
17
18message CreateNoteRequest {
19    string title = 1;
20    string content = 2;
21}
22
23message CreateNoteResponse {
24    Note note = 1;
25}
26
27message GetNotesRequest {}
28
29message GetNotesResponse {
30    repeated Note notes = 1;
31}
32
33message DeleteNoteRequest {
34    string id = 1;
35}
36
37message DeleteNoteResponse {
38    bool success = 1;
39}

This file is the API contract that both the Go backend and the iOS client will use.


2. Backend Implementation: gRPC Go

a. Setting Up Protobuf & gRPC

Make sure you’ve installed protoc , the Go plugins, and the supporting modules:

sh
1go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
2go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

Generate code from the .proto file:

sh
1protoc --go_out=. --go-grpc_out=. note.proto

b. Implementing the Service

Here’s a partial implementation:

go
 1type server struct {
 2    note_pb.UnimplementedNoteServiceServer
 3    notes map[string]*note_pb.Note
 4}
 5
 6func (s *server) CreateNote(ctx context.Context, req *note_pb.CreateNoteRequest) (*note_pb.CreateNoteResponse, error) {
 7    id := uuid.NewString()
 8    now := time.Now().Format(time.RFC3339)
 9    note := &note_pb.Note{
10        Id: id,
11        Title: req.Title,
12        Content: req.Content,
13        CreatedAt: now,
14    }
15    s.notes[id] = note
16    return &note_pb.CreateNoteResponse{Note: note}, nil
17}
18
19// Implement the other methods according to the contract

c. Running the gRPC Server

go
1grpcServer := grpc.NewServer()
2note_pb.RegisterNoteServiceServer(grpcServer, &server{notes: map[string]*note_pb.Note{}})
3lis, _ := net.Listen("tcp", ":50051")
4grpcServer.Serve(lis)

The Go backend is ready!


3. iOS Client: Swift

a. Integrating the Library

gRPC Swift support is available via Swift Package Manager or CocoaPods.

swift
1// swift-tools-version: 5.6
2.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.10.0")

b. Generating Swift Code from Protobuf

Make sure the Swift plugin is installed:

sh
1brew install grpc-swift
2protoc note.proto --swift_out=. --swift-grpc_out=.

c. Creating the Client and Calling the API

swift
 1import GRPC
 2import NIO
 3import Note // generated from the Swift proto
 4
 5let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
 6let channel = try! GRPCChannelPool.with(
 7    target: .host("localhost", port: 50051),
 8    transportSecurity: .plaintext,
 9    eventLoopGroup: group
10)
11let client = Note_NoteServiceClient(channel: channel)
12
13let req = Note_CreateNoteRequest.with {
14    $0.title = "Learning gRPC"
15    $0.content = "Connecting Swift with Go"
16}
17let resp = try! client.createNote(req).response.wait()
18
19print("Successfully created note with id \(resp.note.id)")

4. Flow Diagram

This illustrates the data flow from the client to the server.

MERMAID
sequenceDiagram
    participant iOS as iOS App (Swift)
    participant GoGRPC as gRPC Server (Go)
    iOS->>GoGRPC: RPC CreateNote(title, content)
    GoGRPC-->>iOS: New note + ID
    iOS->>GoGRPC: RPC GetNotes()
    GoGRPC-->>iOS: List of notes

5. Simulation: Creating and Retrieving Data

Steps:

  1. The iOS app sends a CreateNote RPC.
  2. The Go server stores the note and returns a response.
  3. The iOS app sends a GetNotes RPC.
  4. The Go server returns the list of all notes.

Simulation results:

TimeClient ActionServer Response
2024-06-05 10:01CreateNote(“A”)Note(id: “X1”, title: “A”)
2024-06-05 10:02CreateNote(“B”)Note(id: “X2”, title: “B”)
2024-06-05 10:03GetNotes()[Note “X1”, Note “X2”]

6. Tips and Best Practices

  • Versioning: Use Protobuf optional fields for backward compatibility.
  • Transport Security: Enable TLS in production.
  • Error Handling: Use Protobuf error enums.
  • Streaming: Use streaming for real-time sync when needed.

7. Conclusion

gRPC ushers in a new era of efficient communication between applications. The case study above shows how a Go backend and an iOS client can communicate through a clear API contract, with high performance and great maintainability.
This combination is a great fit for modern applications, from microservices to mobile backends.

If you’re building cross-platform applications, set up the Protobuf build process to run automatically in your CI/CD pipeline, use the same dependencies across the whole team, and don’t forget to test across languages—because while gRPC is designed for cross-ecosystem use, each language’s implementation has its own nuances.

Further references:

Happy experimenting with gRPC—and I hope this case study helps you integrate your mobile app and backend more effectively!

Related Articles

💬 Comments