@ScaledMetric — was ist das, SwiftUI Property Wrapper und Dynamic Type

Autor: IT Sectr Veröffentlicht: 2026-06-27 Lesezeit: 10 Min.

@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 — ein SwiftUI-Property-Wrapper zur Skalierung von Werten für Dynamic Type.
  • Dynamic Type — eine iOS-Systemeinstellung, die die Schriftgröße von UIFontTextStyle ändert.
  • Skalierung — @ScaledMetric nimmt einen Basiswert und einen relativeTo-Multiplikator.
  • Automatische Aktualisierung — bei Änderung von Dynamic Type berechnet @ScaledMetric neu und die UI wird aktualisiert.
  • Barrierefreiheit — die Verwendung von @ScaledMetric verbessert die Zugänglichkeit der Oberfläche ohne zusätzlichen Code.

Was ist @ScaledMetric?

@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.

@ScaledMetric Syntax

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.

swift
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.

Wie @ScaledMetric funktioniert

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.

Dynamic-Type-Skalierungsskala

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ößenkategorieFaktor (body)Beispiel @ScaledMetric(12)
extraSmall0.85~10 pt
small0.93~11 pt
medium (default)1.0012 pt
large1.07~13 pt
extraLarge1.15~14 pt
extraExtraLarge1.28~15 pt
accessibilityExtraLarge1.47~18 pt
accessibilityXXXL1.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.

@ScaledMetric und Dynamic Type

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.

Barrierefreiheitstests via Canvas

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.

swift
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.

@ScaledMetric Beispiele

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.

swift
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.

swift
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 vs @State — Unterschiede

@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
AktualisierungsquelleDynamic Type (System)Programmatisch (Entwickler)
WerttypCGFloat, Int, DoubleBeliebig
Änderung aus CodeNicht erlaubtÜber Binding erlaubt
View-NeuzeichnungBei Dynamic-Type-ÄnderungBei Wertänderung
iOS-VersioniOS 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.

Häufige Fehler mit @ScaledMetric

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.

Aktuelle Größenkategorie im Code abrufen

@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.

swift
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

Wie unterscheidet sich @ScaledMetric von @ScaledFont?

@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.

Funktioniert @ScaledMetric auf watchOS und tvOS?

@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.

Kann @ScaledMetric in Komponententests getestet werden?

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.

Wie interagiert @ScaledMetric mit .dynamicTypeSize?

.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.

Was tun, wenn @ScaledMetric die UI nicht aktualisiert?

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

  • @ScaledMetric — ein SwiftUI-Property-Wrapper zur automatischen Zahlenskalierung für Dynamic Type.
  • Bindung — relativeTo bindet die Skala an einen bestimmten Textstil (body, title, caption).
  • Barrierefreiheit — @ScaledMetric verbessert die Zugänglichkeit der Oberfläche ohne manuellen Code.
  • Nur Zahlen — der Wrapper skaliert CGFloat, Int, Double, aber keine Schriftarten.
  • Bereich — von 0.85 (XS) bis 1.71 (XXXL) relativ zum Basiswert.
  • Schreibgeschützt — @ScaledMetric kann nicht aus Code geändert werden, nur über das System.

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.

Projekt besprechen

Lesen Sie auch