Prečo potrebujete Swift Charts v každej dátovo orientovanej aplikácii
Vizualizácia dát nie je luxus — je to nevyhnutnosť. Či už budujete fitness appku, finančný dashboard alebo analytický nástroj, používatelia jednoducho očakávajú prehľadné grafy. A buďme úprimní, pred príchodom Swift Charts ste mali dve (dosť nepríjemné) možnosti: siahnuť po tretej strane ako Charts od Daniela Gindi, alebo sa pustiť do kreslenia pixlov ručne cez CoreGraphics. Oboje bolelo.
Apple to celé zmenil na WWDC 2022 predstavením frameworku Swift Charts.
Od iOS 16 máte k dispozícii deklaratívne, prístupné a výkonné grafy priamo v SwiftUI. A s každou ďalšou verziou pribúdajú nové veci — koláčové grafy v iOS 17, scrollovateľné a interaktívne grafy, a najnovšie Chart3D v iOS 26 pre plnohodnotnú 3D vizualizáciu. Takže poďme sa do toho pustiť.
V tomto sprievodcovi prejdeme od úplných základov až po pokročilé techniky. Každá sekcia obsahuje funkčný kód, ktorý si môžete skopírovať do Xcode a ihneď spustiť — žiadne polotovary.
Základy: Prvý graf za 5 riadkov kódu
Swift Charts funguje na koncepte značiek (marks). Každá značka predstavuje jeden vizuálny prvok v grafe — stĺpec, bod, čiaru alebo sektor. Kombináciou značiek a dát vytvoríte graf. Je to vlastne veľmi intuitívne, keď si na to zvyknete.
Začneme najjednoduchším príkladom — stĺpcovým grafom predajov:
import SwiftUI
import Charts
struct Predaj: Identifiable {
let id = UUID()
let mesiac: String
let suma: Double
}
let predaje = [
Predaj(mesiac: "Jan", suma: 1200),
Predaj(mesiac: "Feb", suma: 1800),
Predaj(mesiac: "Mar", suma: 2400),
Predaj(mesiac: "Apr", suma: 1600),
Predaj(mesiac: "Máj", suma: 3100),
Predaj(mesiac: "Jún", suma: 2700)
]
struct PredajChart: View {
var body: some View {
Chart(predaje) { polozka in
BarMark(
x: .value("Mesiac", polozka.mesiac),
y: .value("Suma", polozka.suma)
)
}
.frame(height: 300)
}
}
To je celé. Päť riadkov v Chart closure a máte plnohodnotný stĺpcový graf s automatickými osami, legendou a podporou VoiceOver. Framework sám určí rozsah osí, formátovanie aj rozloženie — nemusíte riešiť nič ručne.
Všetky typy značiek: BarMark, LineMark, PointMark a ďalšie
Swift Charts ponúka šesť základných 2D značiek. Každá sa hodí na iný typ vizualizácie, tak si ich poďme prejsť.
BarMark — stĺpcové grafy
Ideálne na porovnávanie diskrétnych kategórií. Podporujú horizontálne aj vertikálne rozloženie a skupinové stĺpce:
Chart(predaje) { polozka in
BarMark(
x: .value("Mesiac", polozka.mesiac),
y: .value("Suma", polozka.suma)
)
.foregroundStyle(by: .value("Kategória", polozka.mesiac))
.cornerRadius(6)
}
LineMark — čiarové grafy
Výborné na zobrazenie trendov v čase. Stačí zameniť BarMark za LineMark a máte hotovo:
Chart(predaje) { polozka in
LineMark(
x: .value("Mesiac", polozka.mesiac),
y: .value("Suma", polozka.suma)
)
.interpolationMethod(.catmullRom)
.symbol(Circle())
}
Modifier .interpolationMethod(.catmullRom) vytvorí plynulú krivku namiesto ostrých lomov. Osobne ho používam skoro vždy — graf jednoducho vyzerá lepšie.
AreaMark — plošné grafy
Fungujú rovnako ako LineMark, ale vyplnia oblasť pod čiarou. Skvelo sa hodia na znázornenie objemov alebo kumulatívnych hodnôt:
Chart(predaje) { polozka in
AreaMark(
x: .value("Mesiac", polozka.mesiac),
y: .value("Suma", polozka.suma)
)
.foregroundStyle(
.linearGradient(
colors: [.blue.opacity(0.4), .blue.opacity(0.05)],
startPoint: .top,
endPoint: .bottom
)
)
}
PointMark — bodové grafy (scatter plot)
Na zobrazenie korelácie medzi dvoma premennými. Nič zložité:
Chart(merania) { m in
PointMark(
x: .value("Teplota", m.teplota),
y: .value("Vlhkosť", m.vlhkost)
)
.symbolSize(60)
}
RuleMark — referenčné čiary
Ideálne na zobrazenie priemeru, cieľa alebo prahových hodnôt. Toto je taký skrytý klenot Swift Charts — jednoduchá vec, ale neuveriteľne užitočná v praxi:
Chart {
ForEach(predaje) { polozka in
BarMark(
x: .value("Mesiac", polozka.mesiac),
y: .value("Suma", polozka.suma)
)
}
RuleMark(y: .value("Priemer", 2133))
.foregroundStyle(.red)
.lineStyle(StrokeStyle(lineWidth: 2, dash: [5, 3]))
.annotation(position: .top, alignment: .leading) {
Text("Priemer: 2 133 €")
.font(.caption)
.foregroundStyle(.red)
}
}
RectangleMark — obdĺžnikové oblasti
Na heatmapy alebo zvýraznenie rozsahov v grafe:
RectangleMark(
xStart: .value("Začiatok", startDate),
xEnd: .value("Koniec", endDate),
yStart: .value("Min", 0),
yEnd: .value("Max", 100)
)
.foregroundStyle(.green.opacity(0.15))
Koláčové a donutové grafy so SectorMark (iOS 17+)
Pred iOS 17 ste museli koláčové grafy kresliť ručne cez Path a Arc. Kto to niekedy skúšal, vie, aké to bolo frustrujúce. Od iOS 17 máte SectorMark, ktorý to celé rieši deklaratívne.
Základný koláčový graf
struct Kategoria: Identifiable {
let id = UUID()
let nazov: String
let hodnota: Double
}
let kategorie = [
Kategoria(nazov: "Jedlo", hodnota: 450),
Kategoria(nazov: "Doprava", hodnota: 200),
Kategoria(nazov: "Zábava", hodnota: 150),
Kategoria(nazov: "Bývanie", hodnota: 800)
]
struct KolacovyGraf: View {
var body: some View {
Chart(kategorie) { kat in
SectorMark(
angle: .value("Suma", kat.hodnota)
)
.foregroundStyle(by: .value("Kategória", kat.nazov))
}
.frame(height: 300)
}
}
Framework automaticky vypočíta uhly jednotlivých sektorov podľa pomeru hodnôt. Žiadne ručné počítanie stupňov ani radiánov.
Donutový graf s vnútorným polomerom
Stačí pridať parameter innerRadius a máte krásny donut:
SectorMark(
angle: .value("Suma", kat.hodnota),
innerRadius: .ratio(0.6),
angularInset: 2
)
.cornerRadius(5)
Parameter innerRadius: .ratio(0.6) vytvorí dieru v strede. angularInset pridá medzeru medzi sektormi a cornerRadius zaoblí rohy. Výsledok vyzerá profesionálne a pritom ste na to potrebovali tri riadky kódu.
Interaktívny výber sektora
struct InteraktivnyDonut: View {
@State private var vybranaSuma: Double?
var body: some View {
Chart(kategorie) { kat in
SectorMark(
angle: .value("Suma", kat.hodnota),
innerRadius: .ratio(0.6),
angularInset: 2
)
.foregroundStyle(by: .value("Kategória", kat.nazov))
.opacity(vybranaSuma == nil || vybranaSuma == kat.hodnota ? 1 : 0.4)
}
.chartAngleSelection(value: $vybranaSuma)
.frame(height: 300)
}
}
Modifier .chartAngleSelection automaticky spracováva gestá a ukladá vybranú hodnotu do bindingu. Nevybraté sektory jemne stlmíme cez opacity — jednoduchý, ale efektívny UX trik.
Scrollovateľné grafy pre veľké dátové sady
Keď máte dáta za celý rok — 365 dní — jednoducho ich nemôžete všetky zobraziť naraz. Bolo by to nečitateľné. Od iOS 17 Swift Charts podporuje scrollovanie a funguje to prekvapivo dobre:
struct ScrollovatelnyGraf: View {
@State private var scrollPozicia: Date = .now
var body: some View {
Chart(denniePredaje) { den in
BarMark(
x: .value("Deň", den.datum, unit: .day),
y: .value("Predaj", den.suma)
)
.foregroundStyle(.blue.gradient)
}
.chartScrollableAxes(.horizontal)
.chartXVisibleDomain(length: 30 * 24 * 3600) // 30 dní
.chartScrollPosition(x: $scrollPozicia)
.frame(height: 250)
}
}
Modifier .chartScrollableAxes(.horizontal) zapne horizontálne scrollovanie. .chartXVisibleDomain určuje, koľko dát je viditeľných naraz — tu je to 30 dní. Osi sa scrollujú spolu s grafom a celý zážitok je plynulý.
Interaktívne grafy: výber, anotácie a gestá
Moderné appky vyžadujú, aby používateľ mohol interagovať s grafom — ťuknúť na bod a zobraziť detail. Poznáte to z burzových aplikácií, kde prstom prechádzate po grafe a vidíte hodnoty. Swift Charts to rieši elegantne.
Výber hodnoty na osi X
struct InteraktivnyLineChart: View {
@State private var vybranyDatum: Date?
let data: [DennaStatistika]
var vybranaPolozka: DennaStatistika? {
guard let vybranyDatum else { return nil }
return data.min(by: {
abs($0.datum.timeIntervalSince(vybranyDatum))
< abs($1.datum.timeIntervalSince(vybranyDatum))
})
}
var body: some View {
Chart(data) { polozka in
LineMark(
x: .value("Dátum", polozka.datum),
y: .value("Hodnota", polozka.hodnota)
)
.interpolationMethod(.catmullRom)
if let vybranaPolozka {
RuleMark(x: .value("Výber", vybranaPolozka.datum))
.foregroundStyle(.gray.opacity(0.4))
.annotation(position: .top) {
VStack(spacing: 4) {
Text(vybranaPolozka.datum, format: .dateTime.day().month())
.font(.caption2)
Text("\(vybranaPolozka.hodnota, specifier: "%.0f") €")
.font(.headline)
}
.padding(8)
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 8))
}
}
}
.chartXSelection(value: $vybranyDatum)
.frame(height: 300)
}
}
Keď používateľ potiahne prstom po grafe, .chartXSelection aktualizuje binding s aktuálnym dátumom. Na tomto mieste zobrazíme vertikálnu čiaru (RuleMark) s anotáciou, ktorá ukazuje presnú hodnotu. Celý ten "scrubbing" efekt dostanete v podstate zadarmo.
Kombinácia viacerých značiek v jednom grafe
Tu sa podľa mňa ukazuje skutočná sila Swift Charts — skladateľnosť. Rôzne typy značiek môžete voľne kombinovať v jednom Chart kontajneri:
Chart {
ForEach(mesacnePredaje) { polozka in
BarMark(
x: .value("Mesiac", polozka.mesiac),
y: .value("Predaj", polozka.predaj)
)
.foregroundStyle(.blue.opacity(0.3))
}
ForEach(mesacnePredaje) { polozka in
LineMark(
x: .value("Mesiac", polozka.mesiac),
y: .value("Predaj", polozka.predaj)
)
.foregroundStyle(.blue)
.lineStyle(StrokeStyle(lineWidth: 2))
}
RuleMark(y: .value("Cieľ", 2500))
.foregroundStyle(.orange)
.lineStyle(StrokeStyle(dash: [8, 4]))
}
Stĺpce, čiara a referenčná línia cieľa — všetko v jednom grafe. Informatívne a vizuálne príťažlivé.
Prispôsobenie osí, legiend a farieb
Swift Charts ponúka rozsiahle možnosti prispôsobenia. Poďme sa pozrieť na tie najdôležitejšie.
Vlastné farby
Chart(kategorie) { kat in
BarMark(
x: .value("Kategória", kat.nazov),
y: .value("Hodnota", kat.hodnota)
)
.foregroundStyle(by: .value("Kategória", kat.nazov))
}
.chartForegroundStyleScale([
"Jedlo": .green,
"Doprava": .blue,
"Zábava": .purple,
"Bývanie": .orange
])
Konfigurácia osí
Chart { /* ... */ }
.chartYAxis {
AxisMarks(position: .leading, values: .stride(by: 500)) { value in
AxisGridLine()
AxisValueLabel {
if let v = value.as(Double.self) {
Text("\(Int(v)) €")
}
}
}
}
.chartXAxis {
AxisMarks(values: .automatic) { _ in
AxisValueLabel()
}
}
Skrytie legendy alebo osí
Niekedy chcete minimalistický vzhľad. Stačí jedno volanie:
Chart { /* ... */ }
.chartLegend(.hidden)
.chartYAxis(.hidden)
Chart3D: 3D vizualizácia dát v iOS 26
Na WWDC 2025 Apple predstavil asi najväčšiu novinku vo Swift Charts od ich vzniku — Chart3D. Musím povedať, že keď som to prvýkrát videl, bol som dosť nadšený. Tento nový kontajner umožňuje vytvárať trojrozmerné grafy priamo v SwiftUI, bez SceneKit alebo externých knižníc.
3D bodový graf (scatter plot)
Prechod z 2D na 3D je prekvapivo jednoduchý — v podstate stačí pridať os Z:
import Charts
struct Meranie3D: Identifiable {
let id = UUID()
let teplota: Double
let vlhkost: Double
let tlak: Double
let typ: String
}
struct ScatterPlot3D: View {
let merania: [Meranie3D]
var body: some View {
Chart3D(merania) { m in
PointMark(
x: .value("Teplota", m.teplota),
y: .value("Tlak", m.tlak),
z: .value("Vlhkosť", m.vlhkost)
)
.foregroundStyle(by: .value("Typ", m.typ))
}
.chartXAxisLabel("Teplota (°C)")
.chartYAxisLabel("Tlak (hPa)")
.chartZAxisLabel("Vlhkosť (%)")
.frame(height: 400)
}
}
Existujúce značky PointMark, RuleMark a RectangleMark teraz podporujú parameter Z. Používateľ môže grafom otáčať a skúmať dáta z rôznych uhlov — je to naozaj interaktívne.
SurfacePlot — matematické povrchy
SurfacePlot je trojrozmerná verzia LinePlot. Prijíma closure s dvoma premennými a vykresľuje kontinuálny povrch. Hodí sa napríklad na vedecké vizualizácie alebo jednoducho na to, aby graf vyzeral impozantne:
struct PovrchovyGraf: View {
var body: some View {
Chart3D {
SurfacePlot(x: "X", y: "Y", z: "Z") { x, z in
sin(x) * cos(z)
}
.foregroundStyle(
.linearGradient(
colors: [.blue, .cyan, .green, .yellow, .orange],
startPoint: .bottom,
endPoint: .top
)
)
}
.chartXScale(domain: -3...3)
.chartZScale(domain: -3...3)
.frame(height: 400)
}
}
Framework vyhodnotí výraz pre rôzne hodnoty X a Z a vytvorí plynulý povrch. S tým gradientom to vyzerá naozaj dobre.
Ovládanie kamery a projekcie
Chart3D(merania) { m in
PointMark(
x: .value("X", m.x),
y: .value("Y", m.y),
z: .value("Z", m.z)
)
}
.chart3DPose(Chart3DPose(
azimuth: .degrees(30),
inclination: .degrees(20)
))
.chart3DCameraProjection(.perspective)
Predvolene Chart3D používa ortografickú projekciu — všetko je rovnako veľké bez ohľadu na vzdialenosť. Pre realistickejší dojem prepnite na perspektívnu projekciu. Azimut ovláda horizontálnu rotáciu, inklinácia vertikálnu. A ak chcete interaktívne otáčanie (čo je oveľa zábavnejšie), naviažte pose na @State premennú.
Prístupnosť a najlepšie praktiky
Swift Charts automaticky generuje popis pre VoiceOver, čo je skvelé. Ale sú veci, ktoré stoja za to spraviť navyše:
- Nepretežujte graf dátami — ak máte stovky bodov, zvážte filtrovanie alebo scrollovanie. Menej je niekedy viac.
- Používajte zmysluplné farby — rozlíšiteľné aj pre ľudí s poruchou farebného videnia (na toto sa naozaj často zabúda)
- Pridajte anotácie — kľúčové hodnoty by mali byť čitateľné aj bez interakcie
- Testujte na rôznych zariadeniach — graf, ktorý vyzerá dobre na iPhone 16 Pro Max, môže byť nečitateľný na iPhone SE
- Cachujte dáta — výpočet veľkých datasetov robte mimo
bodyview, inak spomalíte prekresľovanie
Praktický príklad: Finančný dashboard
Tak, poďme spojiť všetko dohromady. Vytvoríme mini finančný dashboard s troma typmi grafov — niečo, čo by ste reálne mohli použiť v produkcii:
struct FinancnyDashboard: View {
let mesacneVydaje: [MesacnyVydaj]
let kategorieVydajov: [KategoriaVydajov]
var body: some View {
ScrollView {
VStack(spacing: 24) {
// Trend výdajov - čiarový graf
GroupBox("Trend výdajov") {
Chart(mesacneVydaje) { v in
AreaMark(
x: .value("Mesiac", v.datum, unit: .month),
y: .value("Suma", v.suma)
)
.foregroundStyle(.blue.opacity(0.2))
LineMark(
x: .value("Mesiac", v.datum, unit: .month),
y: .value("Suma", v.suma)
)
.foregroundStyle(.blue)
}
.frame(height: 200)
}
// Rozdelenie výdajov - donut
GroupBox("Rozdelenie výdajov") {
Chart(kategorieVydajov) { kat in
SectorMark(
angle: .value("Suma", kat.suma),
innerRadius: .ratio(0.55),
angularInset: 2
)
.foregroundStyle(by: .value("Kategória", kat.nazov))
.cornerRadius(4)
}
.frame(height: 250)
}
// Porovnanie mesiacov - stĺpcový graf
GroupBox("Mesačné porovnanie") {
Chart(mesacneVydaje) { v in
BarMark(
x: .value("Mesiac", v.datum, unit: .month),
y: .value("Suma", v.suma)
)
.foregroundStyle(v.suma > 2000 ? .red : .green)
.cornerRadius(4)
}
.frame(height: 200)
}
}
.padding()
}
}
}
Tento dashboard kombinuje tri druhy grafov v jednom ScrollView. Každý graf je zabalený v GroupBox pre vizuálne oddelenie. V produkcii by ste ešte pridali interaktivitu, animácie a načítavanie dát zo SwiftData alebo API — ale ako základ je to solídne.
Často kladené otázky
Aká je minimálna verzia iOS pre Swift Charts?
Základné Swift Charts (BarMark, LineMark, AreaMark, PointMark, RuleMark, RectangleMark) vyžadujú iOS 16. Koláčové grafy so SectorMark prišli v iOS 17. A najnovšie Chart3D a SurfacePlot vyžadujú iOS 26.
Môžem kombinovať Swift Charts s UIKit?
Áno, bez problémov. Swift Charts sú SwiftUI views, takže ich môžete zabaliť do UIHostingController a použiť v existujúcej UIKit aplikácii. Funguje to aj opačne — UIKit views v SwiftUI cez UIViewRepresentable.
Ako animovať prechody medzi dátami v grafe?
Swift Charts podporujú štandardné SwiftUI animácie. Stačí zabaliť zmenu dát do withAnimation { } a graf automaticky animuje prechod. Framework sa postará o plynulú interpoláciu — nemusíte riešiť žiadne keyframes ručne.
Je možné exportovať graf ako obrázok?
Priamo nie, ale dá sa to obísť cez ImageRenderer z iOS 16. Vytvorte inštanciu ImageRenderer(content: vasGrafView) a zavolajte .uiImage alebo .cgImage pre rastrový obrázok.
Aký je výkonnostný limit Swift Charts?
Apple odporúča maximálne niekoľko tisíc dátových bodov na jeden graf. Pri väčších dátových sadách použite vzorkovanie, agregáciu alebo scrollovateľné grafy s obmedzeným viditeľným oknom cez .chartXVisibleDomain. V praxi som zistil, že pri viac ako 5 000 bodoch to už začína spomaľovať.