Lektion 2.6 · Stufe 2 – SwiftUI-Einstieg

Bilder, SF Symbols und Farben

ca. 15 Minuten Lesezeit

Lernziel

Nach dieser Lektion kannst du eigene Bilder einbinden und richtig skalieren, SF Symbols gezielt einsetzen und gestalten, mit Systemfarben und eigenen Farben aus dem Asset-Katalog arbeiten und sicherstellen, dass alles auch im Dark Mode gut aussieht.

Das Problem: Bilder, die nicht passen

Ein Bild in eine App einzubauen, klingt einfach. Bis das Foto riesig über den Bildschirm hinausragt, verzerrt ist oder im Dark Mode ein grelles weißes Rechteck auf schwarzem Hintergrund erscheint.

In dieser Lektion lernst du drei Werkzeuge kennen: eigene Bilder, SF Symbols und Farben, und wie du sie so einsetzt, dass sie auf jedem iPhone und in jedem Modus gut aussehen.

Eigene Bilder

Ins Projekt holen

  1. Öffne im Navigator den Asset-Katalog Assets.
  2. Zieh eine Bilddatei (PNG, JPEG oder HEIC) aus dem Finder in die linke Spalte des Katalogs.
  3. Gib dem Bild einen Namen ohne Leerzeichen, zum Beispiel mountain.

Dann zeigst du es so an:

Swift
Image("mountain")

Erwartetes Ergebnis

Das Bild erscheint, aber vermutlich viel zu groß. Es wird in seiner Originalgröße angezeigt und ragt über den Bildschirm hinaus.

Größe anpassen

Ein Bild ist standardmäßig so groß wie seine Datei. Damit es sich anpassen kann, braucht es zuerst .resizable():

Swift
Image("mountain")
    .resizable()
    .scaledToFit()
    .frame(height: 200)
  • .resizable(): Das Bild darf seine Größe ändern. Ohne diesen Modifier wirken Größenangaben nicht.
  • .scaledToFit(): Es wird so skaliert, dass es komplett sichtbar ist, ohne Verzerrung. Eventuell bleibt Platz frei.
  • .frame(height: 200): Der verfügbare Platz ist 200 Punkte hoch.

Die Alternative zu .scaledToFit() ist .scaledToFill(): Das Bild füllt den Platz vollständig aus, ohne Verzerrung, und ragt dafür über die Ränder hinaus. Mit .clipped() oder .clipShape(...) schneidest du den Überstand ab:

Swift
Image("mountain")
    .resizable()
    .scaledToFill()
    .frame(width: 300, height: 200)
    .clipShape(.rect(cornerRadius: 16))

Fit oder Fill?

  • Fit: Das ganze Bild ist wichtig, Ränder dürfen frei bleiben. Typisch für Produktfotos, Grafiken, Logos.
  • Fill: Die Fläche soll komplett gefüllt sein, Ränder dürfen abgeschnitten werden. Typisch für Hintergründe, Profilbilder, Kacheln.

Runde Profilbilder

Ein Klassiker:

Swift
Image("portrait")
    .resizable()
    .scaledToFill()
    .frame(width: 120, height: 120)
    .clipShape(.circle)
    .overlay {
        Circle().stroke(.white, lineWidth: 4)
    }
    .shadow(radius: 6)

.overlay legt etwas vor die View (Lektion 2.4), hier einen weißen Kreisrand.

Bilder für Barrierefreiheit

Menschen, die nicht sehen können, nutzen VoiceOver: Das iPhone liest vor, was auf dem Bildschirm ist. Bei Bildern weiß es aber nicht, was darauf zu sehen ist. Hilf ihm:

Swift
Image("mountain", label: Text("Berggipfel im Morgenlicht"))

Image("decoration")
    .accessibilityHidden(true)   // rein dekorativ, wird übersprungen

Mehr dazu in Lektion 4.16. Mach es dir aber von Anfang an zur Gewohnheit.

SF Symbols

SF Symbols ist Apples Bibliothek mit Tausenden Symbolen. Du kennst sie seit Lektion 0.3: Image(systemName: "globe").

Die SF Symbols App

Lade dir die kostenlose App SF Symbols von Apples Entwicklerseite. Dort kannst du alle Symbole durchsuchen, ihre Namen kopieren und sehen, ab welcher iOS-Version es sie gibt. Ohne diese App ist es mühsam, den richtigen Namen zu finden.

Symbole verhalten sich wie Schrift

Das Besondere an SF Symbols: Sie verhalten sich wie Text. Sie haben keine feste Bildgröße, sondern passen sich der Schrift an:

Swift
Image(systemName: "heart.fill")
    .font(.largeTitle)
    .foregroundStyle(.red)

Label("Favoriten", systemImage: "heart.fill")
    .font(.headline)
  • Größe über .font(...), und damit wachsen sie mit Dynamic Type mit.
  • Farbe über .foregroundStyle(...).
  • .imageScale(.large) macht sie relativ zum umgebenden Text größer oder kleiner.

Label kombiniert ein Symbol mit einem Text und richtet beide perfekt aus. Du wirst es in Listen, Buttons und Menüs ständig verwenden.

Varianten und Darstellung

Viele Symbole gibt es in mehreren Varianten. Statt den Namen zu ändern, kannst du sie per Modifier wählen:

Swift
Image(systemName: "heart")
    .symbolVariant(.fill)         // wie "heart.fill"

Image(systemName: "bell")
    .symbolVariant(.slash)        // durchgestrichen

Und für mehrfarbige Symbole gibt es Rendering-Modi:

Swift
Image(systemName: "cloud.sun.rain.fill")
    .symbolRenderingMode(.multicolor)

Image(systemName: "wifi")
    .symbolRenderingMode(.hierarchical)
    .foregroundStyle(.blue)
ModusWirkung
.monochromeeine Farbe (Standard)
.hierarchicaleine Farbe in mehreren Abstufungen
.palettemehrere selbst gewählte Farben: .foregroundStyle(.blue, .yellow)
.multicolorApples eingebaute Originalfarben

Symbole animieren

Symbole können sich auch bewegen:

Swift
Image(systemName: "bell.fill")
    .symbolEffect(.bounce, value: notificationCount)

Jedes Mal, wenn sich notificationCount ändert, hüpft die Glocke. Es gibt viele weitere Effekte wie .pulse, .wiggle oder .rotate. Mehr zu Animationen in Lektion 3.23.

Farben

Systemfarben

SwiftUI bringt eine Palette vordefinierter Farben mit:

Swift
Color.red      Color.orange   Color.yellow   Color.green
Color.mint     Color.teal     Color.cyan     Color.blue
Color.indigo   Color.purple   Color.pink     Color.brown
Color.gray     Color.black    Color.white

Wichtig: Diese Farben sind nicht fest. Apple stimmt sie für hellen und dunklen Modus leicht unterschiedlich ab, damit sie überall gut lesbar sind.

Semantische Farben

Noch besser sind Farben, die eine Bedeutung haben statt eines festen Farbtons:

Swift
Text("Haupttext").foregroundStyle(.primary)
Text("Nebentext").foregroundStyle(.secondary)
Button("Aktion") { }.tint(.accentColor)
FarbeBedeutung
.primaryHaupttext: im hellen Modus fast schwarz, im dunklen fast weiß
.secondarygedämpfter Text
.accentColordie Akzentfarbe deiner App, z. B. für Buttons
Color(.systemBackground)Hintergrund: weiß bzw. schwarz
Color(.secondarySystemBackground)leicht abgesetzter Hintergrund für Karten

Die Dark-Mode-Falle

.foregroundStyle(.black) sieht im hellen Modus gut aus und ist im dunklen Modus unsichtbar: schwarzer Text auf schwarzem Grund. Verwende für Texte und Hintergründe deshalb semantische Farben statt .black und .white.

Eigene Farben im Asset-Katalog

Für deine Markenfarben legst du eigene Farben an:

  1. Öffne Assets.
  2. Rechtsklick in die linke Spalte → New Color Set.
  3. Gib der Farbe einen Namen, z. B. Brand.
  4. Rechts im Attributes Inspector stellst du unter Appearances „Any, Dark“ ein. Dann kannst du je eine Variante für hellen und dunklen Modus festlegen.

Verwenden kannst du die Farbe dann so:

Swift
Text("Meine Marke")
    .foregroundStyle(Color("Brand"))

Neuere Xcode-Versionen erzeugen für jede Farbe im Katalog außerdem automatisch einen Namen, den du ohne Anführungszeichen nutzen kannst: Color(.brand) oder kurz .brand. Das hat einen großen Vorteil: Vertippst du dich, meldet Xcode sofort einen Fehler, statt die Farbe einfach nicht anzuzeigen.

Die Akzentfarbe der App

Im Asset-Katalog gibt es bereits eine Farbe namens AccentColor. Sie bestimmt die Grundfarbe deiner App: Buttons, Schalter, Links und markierte Elemente. Änderst du sie dort, ändert sich die ganze App auf einen Schlag.

Farbverläufe und Transparenz

Swift
Rectangle()
    .fill(.blue.gradient)
    .frame(height: 100)

Text("Halbtransparent")
    .padding()
    .background(.orange.opacity(0.3))
  • .gradient erzeugt aus jeder Farbe einen dezenten, eleganten Verlauf.
  • .opacity(0.3) macht eine Farbe zu 30 % sichtbar.

Für Hintergründe, die den Inhalt dahinter durchscheinen lassen, gibt es Materialien: .background(.ultraThinMaterial). Diese milchglasartigen Flächen prägen das moderne iOS-Design. Mehr dazu in Lektion 3.30.

Typische Fehler

Größenänderung ohne Wirkung

Swift
Image("mountain")
    .frame(width: 100, height: 100)

Das Bild bleibt in Originalgröße. .resizable() fehlt und muss vor .frame stehen.

Verzerrtes Bild

Swift
Image("portrait")
    .resizable()
    .frame(width: 200, height: 100)

Ohne .scaledToFit() oder .scaledToFill() wird das Bild auf genau diese Größe gestreckt. Ergänze einen der beiden.

Bild wird nicht angezeigt

Der Name stimmt nicht mit dem Namen im Asset-Katalog überein. Groß- und Kleinschreibung zählt. In der Konsole steht dann eine Meldung wie No image named 'Mountain' found in asset catalog.

Symbol-Name falsch

Image(systemName: "hearts") zeigt einfach nichts an, ohne Fehlermeldung beim Bauen. Prüf den Namen in der SF Symbols App.

.resizable() an der falschen Stelle

Swift
Image("mountain")
    .scaledToFit()
    .resizable()

Fehlermeldung

Value of type 'some View' has no member 'resizable'

.resizable() gibt es nur direkt auf Image. Nach einem anderen Modifier ist es keine Image mehr, sondern eine eingewickelte View (Lektion 2.4). Schreib .resizable() immer als ersten Modifier.

FAQ

Anfänger

Was bedeutet das überhaupt?

Welche Bildgröße sollte meine Datei haben? Für Fotos reicht meist eine Breite von etwa 1.000 bis 2.000 Pixeln. Größere Dateien machen die App unnötig groß. Für Grafiken wie Logos eignen sich Vektorformate wie PDF oder SVG, die in jeder Größe scharf bleiben.

Darf ich SF Symbols frei verwenden? In Apps für Apple-Plattformen ja. Es gibt aber Regeln, etwa dass manche Symbole nur für bestimmte Zwecke gedacht sind. Die SF Symbols App zeigt das an.

Wie finde ich heraus, wie meine App im Dark Mode aussieht? In der Preview mit .preferredColorScheme(.dark) (Lektion 2.3) oder im Simulator unter Settings → Developer → Dark Appearance. Noch schneller: ⇧ ⌘ A im Simulator schaltet um.

Fortgeschritten

Warum verhält es sich so?

Wie lade ich Bilder aus dem Internet? Mit AsyncImage(url: ...). Es lädt das Bild selbst und zeigt währenddessen einen Platzhalter. Das lernst du in Projekt D (Rezept-App).

Was ist der Unterschied zwischen Color und foregroundStyle? Color ist eine View und ein Farbwert. foregroundStyle akzeptiert jeden ShapeStyle: Farben, aber auch Verläufe, Materialien und semantische Stile wie .secondary. Deshalb ist .foregroundStyle flexibler als das ältere .foregroundColor.

Kann ich Farben im Code definieren, die sich an Dark Mode anpassen? Ja, aber das ist umständlicher als im Asset-Katalog. Für eine handvoll Markenfarben ist der Katalog der übliche Weg.

Profi

Was passiert unter der Haube?

Wie geht SwiftUI mit Bildern für verschiedene Bildschirmauflösungen um? iPhones haben Bildschirme mit zwei- oder dreifacher Pixeldichte. Im Asset-Katalog kannst du deshalb Varianten in @1x, @2x und @3x hinterlegen, und das System lädt automatisch die passende. Mit einem einzelnen Vektorbild oder „Single Scale“ übernimmt Xcode das für dich.

Was sind Template-Bilder? Ein Bild im Modus Template (einstellbar im Attributes Inspector oder mit .renderingMode(.template)) wird wie ein SF Symbol behandelt: Nur seine Form zählt, die Farbe kommt aus .foregroundStyle. So passen sich eigene Icons an Akzentfarbe und Dark Mode an.

Übungen

Anfänger

Übung 1: Wetter-Symbole

Zeig nebeneinander drei Wetter-Symbole (sun.max.fill, cloud.rain.fill, cloud.bolt.fill) in der Größe .largeTitle und im Modus .multicolor.

Lösung Übung 1Erst selbst probieren!
Swift
HStack(spacing: 20) {
    Image(systemName: "sun.max.fill")
    Image(systemName: "cloud.rain.fill")
    Image(systemName: "cloud.bolt.fill")
}
.font(.largeTitle)
.symbolRenderingMode(.multicolor)

Weil .font und .symbolRenderingMode weitergegeben werden, reicht es, sie einmal am Stack anzugeben (Lektion 2.4).

Fortgeschritten

Übung 2: Bildkachel

Zieh ein Foto in den Asset-Katalog und gestalte daraus eine Kachel: 300 × 200 Punkte, Bild füllt die Fläche, abgerundete Ecken mit Radius 20, darunter ein Titel. Prüf, wie es mit einem Hoch- und einem Querformat-Foto aussieht.

Profi

Übung 3: Eigene Farbe für hell und dunkel

Leg im Asset-Katalog eine Farbe CardBackground an: im hellen Modus ein sehr helles Grau, im dunklen ein dunkles Grau. Baue eine Karte mit Titel und Text auf diesem Hintergrund und prüf sie in beiden Modi in der Preview.

Zusammenfassung

  • Eigene Bilder kommen in den Asset-Katalog und werden mit Image("name") angezeigt.
  • .resizable() muss zuerst stehen. Dann .scaledToFit() (alles sichtbar) oder .scaledToFill() (Fläche gefüllt).
  • SF Symbols verhalten sich wie Text: Größe über .font, Farbe über .foregroundStyle.
  • Label kombiniert Symbol und Text.
  • Semantische Farben wie .primary und Color(.systemBackground) funktionieren im Dark Mode.
  • Eigene Farben legst du im Asset-Katalog mit Varianten für hell und dunkel an.

Spickzettel

Swift
Image("photo").resizable().scaledToFit().frame(height: 200)
Image("photo").resizable().scaledToFill().frame(width: 100, height: 100).clipShape(.circle)
Image(systemName: "heart.fill").font(.title).foregroundStyle(.red)
Label("Favoriten", systemImage: "star")
.symbolRenderingMode(.hierarchical)
.symbolEffect(.bounce, value: count)
.foregroundStyle(.secondary)
.background(Color(.secondarySystemBackground))
Color("Brand")   .blue.gradient   .orange.opacity(0.3)

Lektion geschafft?

Markiere sie als erledigt, damit du deinen Fortschritt siehst.