@ScaledMetric ist ein SwiftUI-Property-Wrapper, der einen numerischen Wert automatisch entsprechend den Dynamic-Type-Einstellungen des Benutzers skaliert. Der Wert wird in @ScaledMetric eingeschlossen und bei Änderung der Systemschriftgröße neu berechnet, wodurch die Zugänglichkeit der Oberfläche für Menschen mit Sehbehinderungen gewährleistet wird. Laut Apple Developer Documentation (2026) verwendet @ScaledMetric die UIFontMetrics-Skala, um die relative Skala basierend auf der bevorzugten Inhaltsgrößenkategorie zu berechnen. Mehr zur Barrierefreiheit erfahren Sie im SwiftUI-Barrierefreiheitsartikel.
Wichtige Punkte
@ScaledMetric ist ein SwiftUI-Property-Wrapper, der in iOS 14 eingeführt wurde und einen numerischen Wert (CGFloat, Int, Double) automatisch an die aktuelle Dynamic-Type-Schriftgröße anpasst. Im Gegensatz zu .font(.body) für Schriftarten skaliert @ScaledMetric beliebige numerische Parameter: Padding, Spacing, CornerRadius, IconSize — alles, was sich proportional mit größerem Text vergrößern soll.
Der Hauptzweck von @ScaledMetric ist die Bereitstellung von Barrierefreiheits-Skalierung für nicht-textuelle Oberflächenelemente. Wenn der Benutzer die Schriftgröße in den iOS-Einstellungen erhöht, sollten Schaltflächen, Symbole und Abstände proportional skaliert werden, um die Oberfläche ausgewogen zu halten. @ScaledMetric erledigt dies automatisch, ohne manuelle Multiplikatorberechnung.
Basissyntax von @ScaledMetric verwendet einen Standardwert und einen optionalen relativeTo-Parameter. Wenn relativeTo angegeben ist, wird die Skalierung an einen bestimmten Textstil (UIFontTextStyle) gebunden. Wenn nicht, wird die .body-Skala verwendet.
struct AccessibleButton: View {
@ScaledMetric private var padding: CGFloat = 12
@ScaledMetric(relativeTo: .title) private var iconSize: CGFloat = 24
var body: some View {
Label("Submit", systemImage: "checkmark.circle.fill")
.font(.body)
.padding(padding)
.imageScale(.init(rawValue: iconSize / 24) ?? .medium)
}
}
Padding wird relativ zu .body (Standard) skaliert, iconSize relativ zu .title. Bei größerem Text werden Abstände und Symbole proportional vergrößert. Ohne @ScaledMetric würde das Padding unabhängig von der Schriftgröße bei 12 pt bleiben, was zu visuellem Ungleichgewicht führt.
Der @ScaledMetric-Mechanismus basiert auf UIFontMetrics aus UIKit. Wenn SwiftUI eine @ScaledMetric-Instanz erstellt, berechnet es einen Multiplikator basierend auf der aktuellen bevorzugten Inhaltsgrößenkategorie (UIContentSizeCategory). Der Basiswert wird mit dem scaledValue von UIFontMetrics für den angegebenen Textstil multipliziert.
Mathematisch: ScaledMetricValue = baseValue × UIFontMetrics.scaledValue(for: relativeTo). Wenn relativeTo nicht angegeben ist, wird UIFontMetrics.default verwendet, das an .body gebunden ist. Wenn sich Dynamic Type ändert, erstellt SwiftUI den View-Body neu, @ScaledMetric berechnet einen neuen scaledValue und die UI wird automatisch über den @State-ähnlichen PropertyWrappers-Mechanismus aktualisiert.
Die iOS-Skala umfasst 11 Größen: von .extraSmall (5 pt) bis .accessibilityExtraExtraExtraLarge (77 pt für .body). Der Skalierungsfaktor für .body reicht von 0.85 (XS) bis 1.71 (XXXL) relativ zum Basiswert. @ScaledMetric verwendet genau diese Skala, sodass ein Padding-Wert von 12 pt bei maximaler Barrierefreiheitsgröße zu etwa 20 pt werden kann.
| Inhaltsgrößenkategorie | Faktor (body) | Beispiel @ScaledMetric(12) |
|---|---|---|
| extraSmall | 0.85 | ~10 pt |
| small | 0.93 | ~11 pt |
| medium (default) | 1.00 | 12 pt |
| large | 1.07 | ~13 pt |
| extraLarge | 1.15 | ~14 pt |
| extraExtraLarge | 1.28 | ~15 pt |
| accessibilityExtraLarge | 1.47 | ~18 pt |
| accessibilityXXXL | 1.71 | ~20 pt |
Auswahl von relativeTo: Verwenden Sie .body für Werte, die mit Fließtext zusammenhängen (Padding, Spacing in Listen), .title für große Elemente (iconSize, imageSize), .caption für kleine Elemente (Badge-Größe). Dadurch wird sichergestellt, dass Elemente synchron mit dem umgebenden Text skaliert werden.
Dynamic Type ist eine iOS-Funktion, die es Benutzern ermöglicht, die Systemschriftgröße unter Einstellungen → Anzeige & Helligkeit → Textgröße anzupassen. Die Änderung gilt global für alle Apps. @ScaledMetric reagiert automatisch auf diese Änderung: SwiftUI aktualisiert alle @ScaledMetric-Variablen, wenn sich UIContentSizeCategory ändert.
Wichtig: @ScaledMetric skaliert nur numerische Werte, verwaltet aber keine Schriftarten direkt. Verwenden Sie für Schriftarten .font() mit einem Textstil (.body, .title, .headline) — SwiftUI skaliert die Schriftart automatisch. @ScaledMetric ergänzt die Schriftskalierung für Padding, Spacing und Elementgrößen.
Canvas Preview unterstützt Dynamic Type: Die Canvas-Symbolleiste verfügt über einen Schieberegler für die Textgröße (A–A) zum Testen der UI bei verschiedenen Schriftgrößen. Verwenden Sie ihn mit @ScaledMetric, um zu überprüfen, ob Abstände und Größen korrekt skaliert werden.
struct CardView: View {
@ScaledMetric private var cornerRadius: CGFloat = 16
@ScaledMetric private var spacing: CGFloat = 8
var body: some View {
VStack(spacing: spacing) {
Text("Card Title")
.font(.headline)
Text("Description with dynamic type support")
.font(.body)
}
.padding(spacing * 2)
.background(.regularMaterial)
.cornerRadius(cornerRadius)
}
}
struct CardView_Previews: PreviewProvider {
static var previews: some View {
CardView()
.dynamicTypeSize(.large)
.previewDisplayName("Large")
CardView()
.dynamicTypeSize(.accessibility5)
.previewDisplayName("Accessibility 5")
}
}
cornerRadius skaliert von 16 pt auf ~27 pt bei maximaler Barrierefreiheitsgröße. spacing — von 8 auf ~14 pt. Dadurch bleibt die Karte bei jeder Schriftgröße visuell ausgewogen.
Beispiel: Dynamic-Type-unterstütztes Symbol. Image(systemName:)-Symbolgrößen werden standardmäßig nicht an Dynamic Type angepasst. @ScaledMetric löst dieses Problem, indem es imageScale oder die Rahmengröße basierend auf dem aktuellen Skalierungsfaktor ändert.
struct IconLabel: View {
let title: String
let icon: String
@ScaledMetric private var iconDimension: CGFloat = 28
@ScaledMetric(relativeTo: .body) private var spacing: CGFloat = 6
var body: some View {
HStack(spacing: spacing) {
Image(systemName: icon)
.resizable()
.frame(width: iconDimension, height: iconDimension)
Text(title)
.font(.body)
}
}
}
Beispiel: Barrierefreies Badge-Komponente. Ein nummeriertes Badge sollte proportional zum Text skaliert werden. @ScaledMetric für die minimale Badge-Größe stellt sicher, dass das runde Badge bei großem Text sichtbar bleibt.
struct BadgeView: View {
let count: Int
@ScaledMetric(relativeTo: .caption) private var badgeSize: CGFloat = 20
@ScaledMetric(relativeTo: .caption) private var fontScale: CGFloat = 1
var body: some View {
ZStack {
Circle()
.fill(.red)
.frame(width: badgeSize, height: badgeSize)
Text("\(count)")
.font(.caption)
.foregroundColor(.white)
.scaleEffect(fontScale)
}
.fixedSize()
}
}
fontScale skaliert zusätzlich den Inhalt des Circle, um der vergrößerten badgeSize zu entsprechen. Ohne fontScale könnte der Text im Badge bei großem Text nicht passen.
@ScaledMetric und @State sind beides Property Wrapper, die Änderungen verfolgen, jedoch mit unterschiedlichen Aktualisierungsquellen. @State aktualisiert den Wert bei programmatischer Änderung (über $stateBinding). @ScaledMetric aktualisiert den Wert automatisch bei Änderung des systemweiten Dynamic Type, erlaubt jedoch keine direkte Änderung des Werts aus dem Code.
Hauptunterschied: @ScaledMetric ist schreibgeschützt für den Entwickler und schreibgeschützt für das System. Sie können scaledValue nicht über einen Setter ändern — es wird von SwiftUI basierend auf dem Basiswert und dem aktuellen Dynamic Type berechnet. @State hingegen wird vollständig vom Entwickler gesteuert. Wenn Sie einen Wert benötigen, der sowohl an Dynamic Type angepasst als auch programmatisch geändert wird — kombinieren Sie @ScaledMetric mit @State oder verwenden Sie eine berechnete Eigenschaft.
| Eigenschaft | @ScaledMetric | @State |
|---|---|---|
| Aktualisierungsquelle | Dynamic Type (System) | Programmatisch (Entwickler) |
| Werttyp | CGFloat, Int, Double | Beliebig |
| Änderung aus Code | Nicht erlaubt | Über Binding erlaubt |
| View-Neuzeichnung | Bei Dynamic-Type-Änderung | Bei Wertänderung |
| iOS-Version | iOS 14+ | iOS 13+ |
Kombiniertes Muster: Wenn Sie Padding programmatisch ändern müssen (z.B. Tipp-Animation) und gleichzeitig an Dynamic Type anpassen möchten, erstellen Sie ein @ScaledMetric für den Basisskalierungswert und ein @State für den Animationsmultiplikator. Endwert = scaledValue × animationMultiplier.
Fehler 1: @ScaledMetric für Schriftarten verwenden. @ScaledMetric skaliert Zahlen, keine Schriftarten. Verwenden Sie für Schriftarten .font(.body) — SwiftUI wendet Dynamic Type automatisch an. Verwenden Sie @ScaledMetric niemals mit font(.system(size: scaledSize)) — dies beeinträchtigt die Systembarrierefreiheit.
Fehler 2: Fehlendes relativeTo für heterogene Elemente. Wenn Sie Padding (an .body gebunden) und iconSize (an .title gebunden) haben, geben Sie für jedes das korrekte relativeTo an. Ohne relativeTo werden beide nach .body skaliert, was zu einer unverhältnismäßigen Skalierung des Symbols im Verhältnis zu seinem Textkontext führt.
Fehler 3: @ScaledMetric in ViewModel/@ObservableObject. @ScaledMetric ist ein SwiftUI-Property-Wrapper, der nur innerhalb einer View funktioniert. Er kann nicht in ViewModels oder Diensten verwendet werden. Für die Skalierung in ViewModel übergeben Sie den skalierten Wert aus der View als Parameter oder verwenden Sie @Environment(\.sizeCategory) in der View.
@Environment(\.sizeCategory) ist eine alternative Möglichkeit, den aktuellen Dynamic Type in einer View zu erhalten. Verwenden Sie es, wenn Sie mehr Kontrolle benötigen: einen benutzerdefinierten Multiplikator berechnen, sizeCategory an ViewModel übergeben oder für flexible Skalierung mit @ScaledMetric kombinieren.
struct CustomScaledView: View {
@Environment(\.sizeCategory) private var sizeCategory
@ScaledMetric private var basePadding: CGFloat = 12
private var extraPadding: CGFloat {
if sizeCategory >= .accessibilityLarge {
return basePadding * 0.5
}
return 0
}
var body: some View {
Text("Custom scaled content")
.font(.body)
.padding(basePadding + extraPadding)
}
}
Zusätzliches Padding extraPadding wird nur bei Barrierefreiheitsgrößen hinzugefügt und bietet mehr Platz für großen Text, ohne die grundlegende @ScaledMetric-Logik zu ändern.
Häufig gestellte Fragen
@ScaledMetric ist ein offizieller SwiftUI-Property-Wrapper zum Skalieren von Zahlen. @ScaledFont existiert nicht als Standard-API — es ist ein benutzerdefinierter Wrapper, der von der Community implementiert wurde. Verwenden Sie für Schriftarten immer das integrierte .font() mit Textstilen (.body, .title) und @ScaledMetric für Padding, Spacing und Größen.
@ScaledMetric ist verfügbar auf iOS 14+, watchOS 7+, tvOS 14+ und macOS 11+. Auf watchOS ist Dynamic Type auf einen kleineren Bereich beschränkt — Größen von .extraSmall bis .extraLarge sind ohne Barrierefreiheitsgrößen verfügbar. Auf tvOS ist Dynamic Type nicht verfügbar — @ScaledMetric gibt immer den Basiswert zurück.
Ja, erstellen Sie zum Testen von @ScaledMetric eine View mit @ScaledMetric und übergeben Sie den Umgebungs-.sizeCategory-Wert über .environment(\.sizeCategory, .extraExtraLarge). Ermitteln Sie dann die Elementgröße über GeometryReader oder SwiftUI Inspector. Alternativ können Sie die Skalierungslogik über UIFontMetrics in einem separaten Modul testen.
.dynamicTypeSize ist ein View-Modifikator, der den maximalen Dynamic Type für eine Hierarchie begrenzt (z.B. .dynamicTypeSize(...large)). @ScaledMetric respektiert diese Grenze: Wenn .dynamicTypeSize gesetzt ist, überschreitet der skalierte Wert die entsprechende Größe nicht. Kombinieren Sie beide APIs für präzise Steuerung.
Stellen Sie sicher, dass die View @ScaledMetric intern verwendet (nicht in einem ViewModel). Überprüfen Sie, ob die View Dynamic Type abonniert: @ScaledMetric löst automatisch eine Body-Aktualisierung aus, aber wenn die View .equatable() oder .id() verwendet, kann der Mechanismus brechen. Verwenden Sie @Environment(\.sizeCategory) als Fallback.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch