Swiftlang
Art
Lektion 3 von 12
Niveau
Einstieg
Lesezeit
etwa 4 Minuten
Stand

Kontrollfluss in Swift

Mit if und else entscheidet dein Programm, mit guard steigt es früh aus, wenn eine Bedingung nicht erfüllt ist. switch vergleicht einen Wert mit Mustern und muss alle möglichen Fälle abdecken. Wiederholungen schreibst du meist mit for-in über einen Bereich oder eine Collection, seltener mit while.

Danach kannst du

  • schreibst Bedingungen mit if, else if und guard
  • nutzt switch mit Bereichen, Tupeln und where-Bedingungen
  • wählst zwischen for-in, while und repeat-while
  • verstehst, warum switch vollständig sein muss

Voraussetzungen

Umgebung

Swift 6.4.0, Sprachmodus 6
plattformunabhängig, geprüft unter Linux x86-64

if und else

if prüft eine Bedingung vom Typ Bool. Anders als in C braucht die Bedingung keine Klammern, die geschweiften Klammern um den Block sind dafür Pflicht, auch bei nur einer Zeile.

if-guard.swiftAusgeführt Swift 6.4.0, Linux x86-64, 19.10.2026
func bewerte(punkte: Int) -> String {
    if punkte >= 90 {
        return "sehr gut"
    } else if punkte >= 50 {
        return "bestanden"
    } else {
        return "noch nicht bestanden"
    }
}

func anmelden(name: String) -> String {
    guard !name.isEmpty else {
        return "Bitte gib einen Namen ein."
    }
    // Ab hier ist sicher: name ist nicht leer
    return "Willkommen, \(name)!"
}

print(bewerte(punkte: 95))
print(bewerte(punkte: 42))
print(anmelden(name: ""))
print(anmelden(name: "Ada"))

Ausgabe

sehr gut
noch nicht bestanden
Bitte gib einen Namen ein.
Willkommen, Ada!

Die Bedingungen in bewerte werden von oben nach unten geprüft; der erste zutreffende Zweig gewinnt. Deshalb steht >= 90 vor >= 50. In umgekehrter Reihenfolge würde auch eine 95 nur „bestanden“ ergeben.

guard: früh aussteigen

guard ist ein umgedrehtes if: Der else-Block läuft, wenn die Bedingung nicht erfüllt ist, und er muss die Funktion verlassen, etwa mit return oder throw. Der Compiler prüft das. Nach dem guard weißt du deshalb sicher, dass die Bedingung gilt.

Der Vorteil zeigt sich in längeren Funktionen. Statt den eigentlichen Code immer tiefer in if-Blöcke einzurücken, prüfst du am Anfang alle Voraussetzungen und schreibst den Rest ohne Verschachtelung. In der Lektion zu Optionals siehst du guard let, die häufigste Form.

switch: vergleichen mit Mustern

switch vergleicht einen Wert mit mehreren Mustern. In Swift ist das viel mächtiger als in C oder Java: Ein Fall kann ein Bereich sein, ein Tupel, eine Bedingung mit where oder ein Muster, das Werte herauszieht.

switch.swiftAusgeführt Swift 6.4.0, Linux x86-64, 19.10.2026
func beschreibe(_ temperatur: Int) -> String {
    switch temperatur {
    case ..<0:
        return "Frost"
    case 0..<15:
        return "kühl"
    case 15...25:
        return "angenehm"
    default:
        return "heiß"
    }
}

for wert in [-3, 8, 21, 31] {
    print(wert, beschreibe(wert))
}

func lage(_ punkt: (x: Int, y: Int)) -> String {
    switch punkt {
    case (0, 0):
        return "Ursprung"
    case (0, let y):
        return "auf der y-Achse bei \(y)"
    case let (x, y) where x == y:
        return "auf der Diagonalen"
    default:
        return "irgendwo anders"
    }
}

for punkt in [(0, 0), (0, 5), (3, 3), (2, 7)] {
    print(punkt, lage(punkt))
}

Ausgabe

-3 Frost
8 kühl
21 angenehm
31 heiß
(0, 0) Ursprung
(0, 5) auf der y-Achse bei 5
(3, 3) auf der Diagonalen
(2, 7) irgendwo anders

Drei Dinge unterscheiden Swifts switch von dem aus vielen anderen Sprachen:

  • Kein Durchfallen. Nach einem passenden Fall ist Schluss, ein break brauchst du nicht. Mehrere Werte für denselben Fall trennst du mit Komma: case 6, 7:.
  • Muster mit Bindung. case (0, let y) passt auf jeden Punkt mit x gleich 0 und legt den y-Wert in einer neuen Konstante ab.
  • Vollständigkeit. Jeder mögliche Wert muss von einem Fall abgedeckt sein.

Der letzte Punkt sorgt am Anfang für Fehlermeldungen, ist aber eine der nützlichsten Regeln der Sprache:

switch-unvollstaendig.swiftKompiliert absichtlich nicht Meldung von Swift 6.4.0, Linux x86-64, 19.10.2026
enum Ampel {
    case rot, gelb, gruen
}

func darfFahren(_ ampel: Ampel) -> Bool {
    switch ampel {
    case .gruen:
        return true
    case .rot:
        return false
    }
}

Compiler-Meldung

switch-unvollstaendig.swift:6:5: error: switch must be exhaustive
 4 | 
 5 | func darfFahren(_ ampel: Ampel) -> Bool {
 6 |     switch ampel {
   |     |- error: switch must be exhaustive
   |     `- note: add missing case: '.gelb'
 7 |     case .gruen:
 8 |         return true

Der Compiler nennt den fehlenden Fall gleich mit. Bei Int oder String gibt es unendlich viele mögliche Werte, dort brauchst du ein default. Bei einem Enum wie Ampel dagegen kann der Compiler alle Fälle aufzählen. Wenn du hier auf default verzichtest und dem Enum später einen Fall hinzufügst, zeigt dir der Compiler jede Stelle, die du anpassen musst. Mehr dazu in der Lektion zu Enums.

Schleifen

Die häufigste Schleife ist for-in. Sie läuft über einen Bereich, eine Collection oder alles, was das Protokoll Sequence erfüllt.

schleifen.swiftAusgeführt Swift 6.4.0, Linux x86-64, 19.10.2026
// Bereich: 1 bis einschließlich 3
for runde in 1...3 {
    print("Runde \(runde)")
}

// Schrittweite mit stride: 0, 25, 50, 75, 100
let marken = stride(from: 0, through: 100, by: 25).map { "\($0) %" }
print(marken.joined(separator: " | "))

// Index und Wert gemeinsam
for (index, name) in ["Ada", "Grace", "Linus"].enumerated() {
    print(index, name)
}

// while prüft vorher, repeat-while prüft nachher
var kontostand = 100
var monate = 0
while kontostand > 0 {
    kontostand -= 30
    monate += 1
}
print("Nach \(monate) Monaten: \(kontostand) €")

var versuche = 0
repeat {
    versuche += 1
} while versuche < 0
print("repeat lief \(versuche)-mal")

Ausgabe

Runde 1
Runde 2
Runde 3
0 % | 25 % | 50 % | 75 % | 100 %
0 Ada
1 Grace
2 Linus
Nach 4 Monaten: -20 €
repeat lief 1-mal
  • for runde in 1...3 zählt einen Bereich ab. Brauchst du die Zahl nicht, schreibst du for _ in 1...3.
  • stride(from:through:by:) erzeugt Werte mit fester Schrittweite. through schließt das Ende ein, to nicht.
  • enumerated() liefert Paare aus laufender Nummer und Element.
  • while prüft die Bedingung vor jedem Durchlauf und läuft unter Umständen gar nicht.
  • repeat-while prüft danach und läuft deshalb mindestens einmal, wie die Ausgabe zeigt, obwohl versuche < 0 nie erfüllt ist.

Achte auf die Kontostand-Schleife: Sie stoppt bei −20 €, nicht bei 0 €, weil sie erst nach dem Abziehen prüft. Solche Grenzfälle sind die häufigste Fehlerquelle in Schleifen. Probiere aus, was passiert, wenn du die Bedingung auf kontostand >= 30 änderst.

Mit break verlässt du eine Schleife vorzeitig, mit continue springst du zum nächsten Durchlauf. In vielen Fällen sind aber Funktionen wie filter, map oder first(where:) klarer; die lernst du bei den Collections und Closures.

Häufige Fehler

switch must be exhaustive. Ein Fall fehlt. Lies die note: Sie nennt den fehlenden Fall. Füge ihn hinzu oder, bei offenen Wertebereichen, ein default.

Ein Zweig wird nie erreicht. Die Reihenfolge der Bedingungen stimmt nicht; ein weiter gefasster Fall steht vor einem engeren. Bei if-Ketten und bei switch über Zahlenbereiche gewinnt immer der erste passende Fall, der Compiler meldet Überschneidungen dort nicht.

Endlosschleife mit while. Die Bedingung wird im Schleifenkörper nie falsch. Prüfe, ob sich die Variable aus der Bedingung in jedem Durchlauf ändert.

Übungen

  1. Schreibe eine Funktion fizzbuzz(_ n: Int) -> String, die für Vielfache von 15 „FizzBuzz“, von 3 „Fizz“, von 5 „Buzz“ und sonst die Zahl als Text liefert. Gib das Ergebnis für 1 bis 15 aus. Nutze switch mit einem Tupel aus zwei Bool-Werten.
  2. Ändere die Kontostand-Schleife so, dass sie nie ins Minus geht und am Ende ausgibt, wie viel übrig bleibt.
Lösung zu Übung 1
loesung-1.swiftAusgeführt Swift 6.4.0, Linux x86-64, 19.10.2026
func fizzbuzz(_ n: Int) -> String {
    switch (n % 3 == 0, n % 5 == 0) {
    case (true, true):
        return "FizzBuzz"
    case (true, false):
        return "Fizz"
    case (false, true):
        return "Buzz"
    case (false, false):
        return String(n)
    }
}

print((1...15).map(fizzbuzz).joined(separator: " "))

Ausgabe

1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz

Das Tupel (n % 3 == 0, n % 5 == 0) hat genau vier mögliche Werte, und alle vier sind abgedeckt. Deshalb braucht dieses switch kein default.

Lösung zu Übung 2
loesung-2.swiftAusgeführt Swift 6.4.0, Linux x86-64, 19.10.2026
var kontostand = 100
var monate = 0
let rate = 30

while kontostand >= rate {
    kontostand -= rate
    monate += 1
}
print("Nach \(monate) Monaten bleiben \(kontostand) €")

Ausgabe

Nach 3 Monaten bleiben 10 €