macOS-Programmierung mit SwiftUI

Im diesem Tutorial geht es um die Grundlagen zur macOS-Programmierung mit SwiftUI. Ziel ist es – unter Verwendung eines Text-Elements – ein simples Hello-World-Programm zu schreiben. Legt dazu ein neues Projekt an und wählt als Vorlage

> macOS > App

aus.

Im nächsten Dialog vergebt Ihr einen Projektnamen (hier: „HelloWorld“), wählt gegebenenfalls ein Team aus (oder belasst es bei „None“) und gebt einen Organization Identifier ein (umgedrehte URL, siehe Abbildung).

Als Interface muss „SwiftUI“ und als Language „Swift“ ausgewählt sein. Bei „Use Core Data“ und „Include Tests“ sind keine Häkchen zu setzen.

Ein neues Projekt in Xcode anlegen

Die zentrale Datei, mit der wir arbeiten werden, heißt „ContentView“. Sie enthält bereits etwas Code:

import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Ab Xcode 14 sieht der beim Anlegen eines neuen Projekts automatisch generierte Code etwas anders aus. Es wird weiterhin eine Text-View erstellt, zu der aber noch eine Image-View hinzukommt. Beide Elemente sind in einem VStack eingebettet:

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")

        }
        .padding()
    }
}

Im Vorschau-Fenster (rechts vom Code-Fenster) wird das Ergebnis angezeigt. Eventuell müsst Ihr dazu auf den Button „Resume“ klicken. Alternativ kann auch die Tastenkombination option + command + p verwendet werden. Es ist ein kleines Fenster zu sehen, das einen Globus und „Hello, world!“ anzeigt.

App-Vorschau ab Xcode 14
Xcode-Vorschau (ab Xcode 14)

Bei dem Code handelt sich um ein struct mit dem Namen „ContentView“, das dem Protokoll View entsprechen muss. Dieses Protokoll verlangt nach der computed property body. Zurückgegeben wird some view, ein opaque return type. Im Ergebnis soll durch diese ContentView der Text „Hello, world!“ angezeigt werden, was durch das UI-Element Text() erreicht wird.

Bei .padding handelt es sich um einen Modifizierer. Wie sich anhand des Namens vermuten lässt, fügt er zwischen dem Text und der Fensterbegrenzung etwas Freiraum hinzu. Ihr könnt .padding auskommentieren, um einen Eindruck davon zu bekommen, wie es ohne diesen Modifizierer aussehen würde.

Damit ist ein wichtiges Grundprinzip von SwiftUI bereits erklärt: Innerhalb der Struktur ContentView werden die gewünschten Elemente hinzugefügt (hier: Image() und Text()), die dann über Modifizierer weiter angepasst werden können.

Wenn mehrere View-Elemente vorhanden sind, kann es sinnvoll sein, sie in ein VStack oder ein HStack einzubetten. Ein VStack bewirkt, dass die Elemente übereinander (vertikal) angeordnet werden (so wie in diesem Beispiel). Bei Verwendung eines HStacks wrden sie nebeneinander (horizontal) angeordnet. Wird hier also VStack zu HStack geändert, sieht die App wie folgt aus:

Image- und Text-View in einem HStack (SwiftUI)
View-Elemente in einem HStack

Als nächstes befassen wir uns mit Modifizierern (Modifiers). Über sie lassen sich View-Elemente weiter anpassen. Dabei beschränken wir uns nachfolgend auf Text("Hello, world!"). Ein VStack wie auch das Bild benötigen wir nicht, weswegen der Code jetzt so aussieht:

struct ContentView: View {
    var body: some View {

        Text("Hello, world!")
            .padding()
    }
}

Modifizierer

Es gibt zahlreiche Modifizierer. Einen Überblick kann man sich in der Library verschaffen. Bevor ihr sie aber öffnet, achtet darauf, dass sich der Cursor unterhalb der folgenden Zeile befindet:

Text("Hello, world!")

Klickt dann in Xcode oben rechts auf den Plus-Button, um die Library zu öffnen. Klickt dann auf das Schieberegler-Symbol und sucht anschließend in der linken Spalte nach „Font“.

Modifizierer in der Library auswählen

Mit einem Doppelklick auf „Font“ wird jetzt der entsprechende Code hinzugefügt:

struct ContentView: View {
    var body: some View {

        Text("Hello, world!")
            .font(.title) // <- hinzugefügter Modifizierer
            .padding()
    }
}

Anstelle von .title könnte selbstverständlich auch eine andere Auswahl getroffen werden. Ein Doppelklick auf „Font Weight“ fügt beispielsweise folgenden Modifizierer hinzu:

.fontWeight(.bold)

Ein anderer Weg führt über den Attributes inspector. Wenn in der Vorschau ein UI-Element angeklickt wird, erscheinen in der rechten Spalte – im Attributes inspector – die zur Verfügung stehenden Optionen. Bei „Font“ könnte jetzt zum Beispiel „Large Title“ ausgewählt werden.

Attributes Inspector in Xcode

Der Code wird dann dementsprechend aktualisiert:

Text("Hello, world!")
    .font(.largeTitle)
    .padding()

Und es existiert noch eine weitere Möglichkeit. Mit einem Command-Klick auf ein UI-Element im Code oder in der Vorschau öffnet sich ein Kontextmenü, über das unter anderem „Show SwiftUI inspector…“ ausgewählt werden kann. Im sich öffnenden Fenster lassen sich dann ebenfalls die zur Verfügung stehenden Attribute anpassen.

Es ist sinnvoll, mit den zur Verfügung stehenden Modifizierern etwas zu experimentieren. Beispielsweise wäre es hier sinnvoll, die Mindestgröße des UI-Elements vorzugeben, damit „Hello, world!“ auch vollständig angezeigt werden kann:

Text("Hello, world!")
    .font(.largeTitle)
    .frame(minWidth: 300, minHeight:100)
    .padding()

Zum Abschluss werfen wir noch einen Blick auf einen weiteren Modifizierer: .background. Damit soll als Hintergrund die Farbe orange hinzugefügt werden:

Text("Hello, world!")
    .font(.largeTitle)
    .background(.orange)
    .frame(minWidth: 300, minHeight:100)
    .padding()

In der Vorschau sollte jetzt folgendes Ergebnis zu sehen sein:

font and background modifier in combination
„Hello, world!“ in der Xcode-Vorschau

Durch das Hinzufügen von background() hinter font() wurde nur der Hintergrund des Schriftzugs „Hello, world!“ orange eingefärbt. Soll hingegen der komplette Bereich orange werden, muss background() hinter frame() erscheinen. Außerdem wird padding() entfernt:

Text("Hello, world!")
    .font(.largeTitle)
    .frame(minWidth: 300, minHeight:100)
    .background(.orange)
font and frame modifier in combination
Vorschau mit orangem Hintergrund

Dieses Beispiel zeigt, dass es entscheidend sein kann, in welcher Reihenfolge die Modifizierer hinzugefügt wird.

Zuletzt aktualisiert am 16. Juni 2023