Your First iOS & SwiftUI App: Polishing the App

Mar 1 2022 Swift 5.5, iOS 15, Xcode 13

Part 4: A Second Screen

39. Connect the Leaderboard

Lesson Complete

Play Next Lesson
Next
Save for later
About this episode
See versions

See forum comments
Cinema mode Mark as Complete Download course materials
Previous episode: 38. Challenge: Leaderboard Data Model Next episode: 40. App Icon & Display Name

This video was last updated on Mar 1 2022

Now that we have the data model in place, it’s time to hook it up to the leaderboard view.

Rather than just displaying a single hardcoded row, we will now display one row for each leaderboard entry.

To do this, we will make use of our old friend ForEach, which you may recall helped us create a bunch of Ring Views in the background.

We’ll also use a new SwiftUI View called ScrollView, which will make the view scrollable if there are more entries than can fit on one screen. Let’s try this out.

Add to LeaderboardView:

@Binding var game: Game

Update LeaderboardView_Previews:

struct LeaderboardView_Previews: PreviewProvider {
  static private var leaderboardIsShowing = Binding.constant(true)
  static private var game = Binding.constant(Game())

  static var previews: some View {
    LeaderboardView(leaderboardIsShowing: leaderboardIsShowing, game: game)
      .environment(\.horizontalSizeClass, .compact)
    LeaderboardView(leaderboardIsShowing: leaderboardIsShowing, game: game)
      .previewLayout(.fixed(width: 568, height: 320))
    LeaderboardView(leaderboardIsShowing: leaderboardIsShowing, game: game)
      .preferredColorScheme(.dark)
      .environment(\.horizontalSizeClass, .compact)
    LeaderboardView(leaderboardIsShowing: leaderboardIsShowing, game: game)
      .previewLayout(.fixed(width: 568, height: 320))
      .preferredColorScheme(.dark)
  }
}

And in BackgroundView:

LeaderboardView(leaderboardIsShowing: $leaderboardIsShowing, game: $game)

In LeaderboardView, replace RowView with:

VStack(spacing: 10) {
  ForEach(game.leaderboardEntries.indices) { i in
    let leaderboardEntry = game.leaderboardEntries[i]
    RowView(index: i + 1, score: leaderboardEntry.points, date: leaderboardEntry.date)
  }
}

We see no test data. To fix this, add to Game.swift:

init(loadTestData: Bool = false) {
  if loadTestData {
    leaderboardEntries.append(LeaderboardEntry(points: 100, date: Date()))
    leaderboardEntries.append(LeaderboardEntry(points: 80, date: Date()))
    leaderboardEntries.append(LeaderboardEntry(points: 60, date: Date()))
    leaderboardEntries.append(LeaderboardEntry(points: 40, date: Date()))
    leaderboardEntries.append(LeaderboardEntry(points: 20, date: Date()))
  }
}

Update Leaderboard_Previews:

static private var game = Binding.constant(Game(loadTestData: true))

Wrap the VStack in a ScrollView:

ScrollView {
  VStack(spacing: 10) {
    ForEach(game.leaderboardEntries.indices) { i in
      let leaderboardEntry = game.leaderboardEntries[i]
      RowView(index: i + 1, score: leaderboardEntry.points, date: leaderboardEntry.date)
    }
  }
}

Build & run. Add a bunch of entries, and show it worknig.

Show how the X button now appears on top of the view, since not enough padding. To fix, add to bottom of HeaderView:

.padding(.top)