How to Build a Golf Scorecard App in SwiftUI
A Golf Scorecard app lets players record strokes hole-by-hole, track score-to-par in real time, and review round history with beautiful Charts. It's ideal for weekend golfers who want an offline-first, distraction-free companion on the course.
Prerequisites
- Xcode 16 or later installed on macOS Sequoia or higher
- Basic familiarity with SwiftUI views, bindings, and the
@Observable/ SwiftData stack - An Apple Developer account (free tier works for Simulator; $99/yr required for TestFlight and App Store)
Step-by-Step Build
1. Define the Round data model with SwiftData
Create a persistent Round model that stores the course name, date, and arrays for par values and stroke counts across all 18 holes.
import SwiftData
@Model final class Round {
var course: String
var date: Date = .now
var holePars: [Int] = Array(repeating: 4, count: 18)
var holeStrokes: [Int] = Array(repeating: 0, count: 18)
var totalStrokes: Int { holeStrokes.reduce(0, +) }
var scoreToPar: Int {
totalStrokes - holePars.reduce(0, +)
}
}
2. Build the scorecard list view
Render each hole as a row with a par Stepper and a strokes Stepper so golfers can quickly adjust values without a keyboard.
struct ScorecardView: View {
@Bindable var round: Round
var body: some View {
List(0..<18, id: \.self) { i in
HStack {
Text("Hole \(i + 1)").frame(width: 64, alignment: .leading)
Stepper("Par \(round.holePars[i])",
value: $round.holePars[i], in: 3...5)
Stepper("\(round.holeStrokes[i])",
value: $round.holeStrokes[i], in: 0...20)
}
}
.navigationTitle(round.course)
}
}
3. Implement stroke tracking with live score-to-par
Present a large-tap counter view for the active hole that updates holeStrokes instantly and shows the running score-to-par in a color-coded badge.
struct StrokeTrackerView: View {
@Bindable var round: Round
@State private var hole = 0
var diff: Int { round.holeStrokes[hole] - round.holePars[hole] }
var body: some View {
VStack(spacing: 24) {
Text("Hole \(hole + 1)").font(.title.bold())
Text(diff == 0 ? "E" : diff > 0 ? "+\(diff)" : "\(diff)")
.font(.headline).foregroundStyle(diff > 0 ? .red : .green)
HStack(spacing: 40) {
Button { if round.holeStrokes[hole] > 0 { round.holeStrokes[hole] -= 1 } } label: {
Image(systemName: "minus.circle.fill").font(.system(size: 52))
}
Text("\(round.holeStrokes[hole])").font(.system(size: 64, weight: .bold))
Button { round.holeStrokes[hole] += 1 } label: {
Image(systemName: "plus.circle.fill").font(.system(size: 52))
}
}
}
}
}
Common Pitfalls
- Array index crashes: SwiftData model arrays default to empty on first launch — always initialise
holeParsandholeStrokeswith 18 elements in the model initialiser or a migration plan. - CoreLocation permissions timing: If you add course auto-detection via
CLLocationManager, requestrequestWhenInUseAuthorization()only after the user taps "Start Round," not on app launch — App Store reviewers flag premature permission requests. - Charts data shape: The
Chartsframework expectsIdentifiabledata points; wrap your(hole, strokes)pairs in a lightweight struct conforming toIdentifiablebefore passing them toBarMark.
Monetization with a Subscription
A subscription model works well for a Golf Scorecard app because committed golfers play year-round and expect ongoing improvements like handicap tracking, GPS overlays, and social leaderboards. Use StoreKit 2's Product.SubscriptionInfo to offer a monthly or annual plan — gate premium features (unlimited round history, Charts analytics, CoreLocation course detection) behind a Transaction.currentEntitlements check, and surface the paywall with ProductView from StoreKit so the system handles receipt validation automatically.
Ship Faster with Soarias
Soarias scaffolds your entire Golf Scorecard app — SwiftData model, 18-hole scorecard view, StrokeTrackerView, StoreKit subscription paywall, and App Store metadata — from a single prompt in Claude Code, cutting the boilerplate phase from days to minutes. The one-time $79 local-first desktop app runs entirely on your Mac, so your code and API keys never leave your machine.
Related Tutorials
FAQ
Do I need an Apple Developer account to build this?
No — you can build and run the Golf Scorecard app on the iOS Simulator for free. You only need a paid Apple Developer account ($99/yr) when you want to install the app on a physical iPhone, distribute via TestFlight, or submit to the App Store.
How do I submit my Golf Scorecard app to the App Store?
Archive your app in Xcode (Product → Archive), validate and upload via the Organizer window, then complete your App Store Connect listing — screenshots, privacy nutrition labels, and a review note explaining the StoreKit subscription. Apple typically reviews new apps within 24–48 hours. Soarias automates the screenshot generation and metadata steps so you can focus on the golf features.
Last reviewed: 2026-05-12 by the Soarias team.