SwiftUI.cc
Snippets
DrawingChartsIntermediate

Swift Charts Marks: Bar, Line, and Sector

Swift Charts builds charts from marks — BarMark, LineMark, PointMark, AreaMark, SectorMark — each mapping data fields to visual position, with foregroundStyle(by:) for series.

5 min readUpdated 2026-06
Weekly sales bars with a goal line
import SwiftUI
import Charts

struct SalesChart: View {
    struct Day: Identifiable {
        let id = UUID()
        let name: String
        let sales: Int
    }

    let week = [
        Day(name: "Mon", sales: 12), Day(name: "Tue", sales: 19),
        Day(name: "Wed", sales: 8),  Day(name: "Thu", sales: 22),
        Day(name: "Fri", sales: 17)
    ]

    var body: some View {
        Chart {
            ForEach(week) { day in
                BarMark(
                    x: .value("Day", day.name),
                    y: .value("Sales", day.sales)
                )
                .foregroundStyle(.teal.gradient)
            }
            RuleMark(y: .value("Goal", 15))
                .lineStyle(StrokeStyle(lineWidth: 1, dash: [4]))
                .annotation(position: .top, alignment: .trailing) {
                    Text("Goal").font(.caption2)
                }
        }
        .frame(height: 220)
        .padding()
    }
}

Swift Charts preview

Marks are the grammar

A chart is a composition of marks, each declaring how data fields map to visual channels:

Chart(readings) { r in
    LineMark(x: .value("Time", r.time), y: .value("°C", r.temp))
    PointMark(x: .value("Time", r.time), y: .value("°C", r.temp))
}

Axes, scales, gridlines, and labels derive from the data automatically — dates get date axes, numbers get sensible ticks.

Series by style

foregroundStyle(by: .value("City", r.city)) turns one mark declaration into N colored series with a legend. The same by: pattern works for symbol (point shapes) and lineStyle (dash patterns), so series stay distinguishable without manual color tables.

Parts of a whole

Chart(shares) { s in
    SectorMark(angle: .value("Share", s.value),
               innerRadius: .ratio(0.6),
               angularInset: 1.5)
        .foregroundStyle(by: .value("Name", s.name))
}

innerRadius turns pie into donut; the center hole is prime real estate for a total via chartBackground overlay.

Annotation layers

RuleMark draws thresholds, RectangleMark highlights ranges, and .annotation(position:) attaches labels to any mark — the building blocks of charts that explain themselves.

Common mistakes

  • Unlabeled .value fields producing cryptic axes and VoiceOver output.
  • Hand-assigning series colors when by-styling exists.
  • Unframed charts expanding to fill whole screens.

Related reference