November 22nd, 2023

Building an airline seat map in SwiftUI

I've been asked to do a tutorial about building an airline seat map in SwiftUI many times. This has been my go-to snippet for years! It's super customizable and provides an awesome starter for any iOS developer in aviation.

Max Alexander

Max Alexander

CPO and CoFounder of Ditto

If you've ever booked a flight, you're familiar with the seat map where you choose your preferred seat. In this tutorial, we'll replicate this feature using SwiftUI.

Step 1: Define the Data Model

Let's start by defining our data model:

enum SeatState { case empty case occupied } struct SeatId: Equatable, Hashable { var row: Int var letter: String } struct Seat: Identifiable, Equatable { var id: SeatId var state: SeatState }

Here, each Seat has an id (consisting of its row and letter) and a state (which can be either empty or occupied).

Step 2: Create the Seat View

We need a visual representation of our seat:

struct SeatView: View { var seat: Seat var body: some View { Text(seat.id.letter) .frame(width: 40, height: 40) .background(seat.state == .empty ? Color.green : Color.red) .cornerRadius(8) .overlay( RoundedRectangle(cornerRadius: 8) .stroke(Color.black, lineWidth: 2) ) } }

The SeatView displays the seat letter and changes its background based on its state.

Step 3: Build the Seat Map

Our goal is a grid layout with 2 seats, an aisle with a row number, 3 seats, another aisle, and then 2 more seats:

struct FirstClassView: View { @State var seats: [Seat] = (1..<25).map { row in ["A", "B", "C", "D", "E", "F", "G"].map { letter in Seat(id: SeatId(row: row, letter: letter), state: .empty) } }.flatMap { $0 } var columns: [GridItem] = [ .init(.flexible()), // A seat .init(.flexible()), // B seat .init(.fixed(40)), // Aisle with row number .init(.flexible()), // C seat .init(.flexible()), // D seat .init(.flexible()), // E seat .init(.fixed(40)), // Aisle with row number .init(.flexible()), // F seat .init(.flexible()) // G seat ] var body: some View { ScrollView([.vertical, .horizontal], showsIndicators: true) { LazyVGrid(columns: columns, spacing: 20) { ForEach(seats) { seat in switch seat.id.letter { case "A", "B", "C", "D", "E", "F", "G": SeatView(seat: seat) .onTapGesture { toggleSeat(seat: seat) } default: Spacer() } if seat.id.letter == "B" || seat.id.letter == "E" { Text("\(seat.id.row)") .font(.headline) .frame(width: 40, height: 40) } } } .padding() } } func toggleSeat(seat: Seat) { if let index = seats.firstIndex(of: seat) { seats[index].state = seats[index].state == .empty ? .occupied : .empty } } }

With SwiftUI, building complex layouts becomes a breeze. Our seat map, with different configurations and aisles, is just a demonstration of how adaptable and flexible SwiftUI grids can be.

Remember, you can further customize the appearance, add more features like zooming, selecting multiple seats, or fetching seat availability from a server. The possibilities are limitless! Happy coding!

Get posts in your inbox

Subscribe to updates and we'll send you occasional emails with posts that we think you'll like.