„Papa, ich möchte Swift lernen und Apps entwickeln“, sagte mein vierzehnjähriger Sohn.
Ich musste ein verblüfftes Gesicht gemacht haben, denn er schob direkt hinterher: „Du kannst mir doch helfen, oder?“
Klar kann ich dir helfen, dachte ich, aber…
Es war nicht so, dass ich das Erlernen von Swift für zu schwierig hielt. Auch hielt ich seine Idee nicht für eine kurzfristige Laune oder Modeerscheinung. Ich befürchtete eher, dass mein Sohn sich ein zu hohes Ziel gesetzt hatte und auf dem Weg, es zu erreichen, die Lust verlieren könnte.
Immerhin wollte er Apps entwickeln, wahrscheinlich ein Spiel, mit dem er Geld verdienen konnte. Und das alles innerhalb von zwei bis drei Wochen.
Eine App zu programmieren, erfordert nicht nur die Beherrschung der Programmiersprache selbst. Vielmehr muss man die zahlreichen Frameworks verstehen, die zur Entwicklung einer App benötigt werden. Nicht zu vergessen das objektorientierte Paradigma, das Swift erfüllt. Doch sollte ich ihm das alles sagen und seine Motivation gleich im Ansatz demontieren?
Innerlich seufzte ich und antwortete: „Cool, ich helfe dir. Du musst nur eine Kröte schlucken: Die Sprache ist so neu, dass fast alles, was es dazu im Netz gibt, auf Englisch geschrieben ist.“
„Auf Youtube habe ich ein Tutorial auf Deutsch gefunden“, antwortete er und lächelte süffisant.
Na toll, also geht es auch ohne Kröte. Nicht lesen, sondern sehen und hören. Schöne neue Welt! Ich bin sowas von old school, dachte ich.
So oder so ähnlich trug mein Sohn vor etwas mehr als einem Jahr sein Anliegen an mich heran. Was danach kam, war Folgendes: Er arbeitete das Video-Tutorial ab und ich unterstützte ihn überall dort, wo er Dinge nicht verstand. Schnell merkte ich, dass das Tutorial lediglich die Sprache erklärte. Es war so, als lernte man Worte und einfache Grammatik, nicht aber, wie aussagekräftige Sätze gebildet werden.
Um die Lücken zu schließen, stellte ich meinem Sohn Aufgaben, die ihn dazu zwangen, das Erlernte anzuwenden. Es war verblüffend, wie viel Wissen neben dem Erlernen der nackten Sprache notwendig ist, damit man diese auch adäquat anwenden kann. Ich musste oft weit ausholen, damit ich ihm eine kleine Entscheidung begreiflich machen konnte. Das alles machte mir großen Spaß – und meinem Sohn auch, denke ich.
Schließlich entwickelte er seine erste kleine iOS-App, die er dann mit großem Stolz seiner Familie, seinen Freunden und seinem Lehrer zeigte.
Meine Geschichte wäre im Grunde hier zu Ende; immerhin hatte mein Sohn sein Ziel erreicht. Nur habe ich zwei Söhne und der zweite schlägt in die gleiche Kerbe. Daher habe ich dieses Mal beschlossen, selbst ein Tutorial zu schreiben, das alle meine Vorstellungen darüber erfüllt, was ein Tutorial enthalten und wie es das Wissen vermitteln sollte.
Worum geht es in dem Tutorial?
Ich richte mich speziell an Schüler, die Interesse haben, Swift zu lernen. Das heißt nicht, dass der Rest der Bevölkerung ausgeschlossen ist. Ich bin davon überzeugt, dass jeder von einem gut strukturierten Tutorial profitieren kann — hoffentlich gelingt mir das. Um das zu erreichen habe ich mir Folgendes überlegt:
- Zu Beginn erkläre ich, welches Programm wir gemeinsam im Laufe dieses Tutorials entwickeln werden. Ich werde NICHT die Sprache Swift anhand isolierter Beispiele beschreiben. Stattdessen wird das Programm sukzessive wachsen und somit ergibt sich genügend Gelegenheit, die Sprache organisch und lebendig kennenzulernen. Die Entwicklung des Programms ist der rote Faden, der sich durch dieses Tutorial zieht.
- Jedes Mal, wenn ich eine neue Eigenschaft der Sprache einführe, verlasse ich kurz den roten Faden, erkläre die Spracheigenschaft und kehre schließlich zurück. Das neu erworbene Wissen kann somit sofort angewendet werden.
- Ich werde im Laufe der Tutorials verschiedene Wege aufzeigen, wie Probleme gelöst werden können. Auch Sackgassen oder falsche Pfade. Auf diese Weise wird der Leser besser verstehen können, warum eine Lösung gut oder schlecht sein kann.
Los geht's: eine Taschenrechner-App mit Swift
Gut, dann legen wir los und programmieren jetzt einen Taschenrechner mit Swift.
Um starten zu können, muss zunächst das Programm Xcode aufgerufen werden. Xcode ist das Hauptwerkzeug, mit dem Programme für Mac, iPhones, iPads oder appleTV implementiert werden. Es kann direkt über den App Store kostenlos heruntergeladen werden – oder über die Developer-Seite von Apple. In beiden Fällen ist eine Apple ID notwendig, die aber kostenlos ist.
Nachdem Xcode auf dem Mac installiert ist, startest du das Programm. Es liegt wie alle anderen Programme unter “Programme”.
Ein neues Projekt kannst du über den Menüpunkt File / New / Project… neu erstellen.
Sobald du das getan hast, erscheint ein Dialogfenster, wie auf dem Bild zu sehen ist. Darin kannst du die Art des Projektes sowie das Betriebssystem, für das du programmieren möchtest, auswählen. In unserem Fall wollen wir für die macOS-Plattform entwickeln, und zwar ein Command Line Tool. Damit ist ein Programm gemeint, das auf einem Mac ablaufen soll und keine graphische Benutzeroberfläche besitzt.
Wähle wie auf dem Bild gezeigt die Plattform und Art des Projekts aus. Dann klicke auf Next.
Wieder erscheint ein Dialogfenster, in dem du einige zusätzliche Information beisteuern musst. Zunächst gibst du unter Product Name den Namen des Projektes an. Tippe “Taschenrechner” ein. Team kannst Du ignorieren. Unter Organization Name kannst du deinen eigenen Namen eingeben, es sei denn du besitzt eine Firma oder arbeitest für eine. Ich habe hier meinen eigenen Namen eingegeben.
Der Organization identifier ist eine eher technische Kurzbezeichnung, um dich oder deine Firma eindeutig zu identifizieren. Tippe de gefolgt von einem Punkt, gefolgt von deinen Initialen (oder dem Firmennamen). Automatisch wird der so genannte Bundle identifier erzeugt, der aus deinem Organization identifier und dem Product Name zusammengesetzt ist. Schließlich wählst du als Programmiersprache Swift aus. Klicke jetzt auf Next.
Jetzt wählst du ein Verzeichnis aus, in dem das Projekt angelegt werden soll und beendest deine Wahl, indem Du auf Create klickst.
Das Projekt wird angelegt und ein Fester erscheint, das in etwa so aussieht, wie oben dargestellt. Klicke jetzt auf die Datei main.swift. Jetzt kann es richtig losgehen.
Das Projekt ist erstellt, nun öffnen wir die Datei main.swift.
Tippe folgende Zeile ein:
// 1. Versuch print("1 + 1 = 2")
Jetzt musst du das Programm kompilieren und anschließend ausführen. Das kannst du mit der Tastenkombination ⌘ + R erreichen. Du kannst auch den Button mit dem Dreieck anklicken.
Um zu sehen, was dieses kleine Programm tut, muss der Konsolenbereich sichtbar sein. Der Konsolenbereich befindet sich unter dem Programmeditor, in dem du gerade deine erste Zeile eingetippt hast. Falls der Konsolenbereich nicht sichtbar ist, findest du in der oberen rechten Ecke des Xcode-Fensters einen Button, mit dessen Hilfe der Konsolenbereich sichtbar gemacht wird. Es ist der zweite Button von rechts – siehe Bild:
Im Konsolenbereich müsste folgende Ausgabe zu sehen sein:
1 + 1 = 2
Hey, super! Unser Taschenrechner kann schon mal 1 + 1 rechnen – oder? Kann er das wirklich? Spaß beiseite, das kann er natürlich nicht. Die Programmzeile
print(1 + 1 = 2)
hat lediglich bewirkt, dass ein Text ausgegeben wird. Ein Text, der zufällig wie eine Rechnung aussieht. Wir hätten ebenso Folgendes schreiben können:
print("Eins plus eins ergibt 2")
In diesem Falle erscheint im Konsolenbereich genau der Text, der zwischen den Gänsefüßchen geschrieben steht. Die Funktion print ist also in der Lage einen beliebigen Text auszugeben. Schön und gut, und was hat das mit einem Taschenrechner zu tun? Nun, die Funktion print bzw. Swift kann noch mehr.
Tippe jetzt folgende Zeile ein:
// 2. Versuch print("1 + 1 = \(1 + 1)")
Führe das Programm aus und du wirst im Konsolenfenster die gleiche Ausgabe vorfinden wie zuvor, nämlich 1 + 1 = 2. Doch was ist diesmal anders? Die Antwort ist, dass \(1 + 1) tatsächlich ausgerechnet worden ist.
Die Funktion print hat also eine Zeichenkette “1 + 1 = ” ausgegeben und anschließend das Ergebnis der Summe 1 + 1. Das ist durch die besondere Schreibweise \(X) geschehen. Hier passiert Folgendes: X wird zunächst von dem Swift-Compiler ausgewertet ( – stell dir unter einem Compiler ein Programm vor, das Swift liest und in etwas umwandelt, das der Rechner ausführen kann, also Maschinencode). Dann wird das Ergebnis dieser Auswertung der Funktion print übergeben. Und schließlich gibt die Funktion den ausgewerteten Wert aus.
Ich weiß, auch das ist kein wirklicher Taschenrechner. Aber immerhin haben wir einen Weg gefunden, mathematische Ausdrücke von Swift berechnen zu lassen. Wir können ja auch Folgendes schreiben:
// 3. Versuch print("1 + 3 * 7 - 4 / 2 = \(1 + 3 * 7 - 4 / 2)")
Im Konsolenbereich werden wir jetzt die Ausgabe 1 + 3 * 7 - 4 / 2 = 20 vorfinden, was ein korrektes Ergebnis darstellt. Die hier verwendeten Operatoren sind Addition +, Subtraktion -, Multiplikation * und Division /. Wie oben erwähnt, führt der Ausdruck \(X) dazu, dass X von der Funktion print ausgewertet wird. Neben mathematischen Ausdrücken kann X auch eine Variable oder Konstante sein. Um dies besser zu erklären, tippe Folgende Zeilen ein:
// 4. Versuch let aufgabe = "1 + 1" let ergebnis = 1 + 1 print("\(aufgabe) = \(ergebnis)")
Auch hier erhalten wir ein korrektes Ergebnis, wenn wir das Programm ausführen. Das Ergebnis ist wieder 1 + 1 = 2. Doch diesmal haben wir Platzhalter für die auszugebenden Werte definiert. Das geschieht hier durch die Anweisungen let aufgabe = 1 + 1”
und let ergebnis = 1 + 1
. let ist ein Schlüsselwort der Programmiersprache Swift und ist für die Einführung einer neuen Konstanten zuständig. Das heißt, die Konstante aufgabe steht für “1 + 1”, während die Konstante ergebnis für das Ergebnis der Auswertung des mathematischen Ausdrucks 1 + 1 steht. Oder anders ausgedrückt: Die Konstante aufgabe kann Zeichenketten speichern und in diesem Beispiel speichert sie die Zeichenkette “1 + 1”. Die Konstante ergebnis hingegen speichert Zahlen; in diesem Falle die Zahl 2.
Eine ausführliche Einführung in Konstanten und Variablen findest du, wenn du den folgenden Themenblock “Konstanten und Variablen” aufklappst. Alternativ kannst du natürlich auch einfach weiterlesen.
Sowohl Konstanten als auch Variablen repräsentieren Namen, die mit einem Wert eines bestimmten Typs verbunden sind. So kann der Name Alter mit dem Wert 42 vom Typ Zahl verbunden sein, wie im Satz: Mein Alter ist 42. Oder vielleicht etwas mathematischer: Alter = 42. Ein anderes Beispiel könnte der Name Hobby sein, der mit dem Wert Radfahren verbunden ist, der wiederum vom Typ Zeichenkette (engl. String) ist. Der einzige Unterschied zwischen Konstanten und Variablen ist die Fähigkeit, den Wert, mit dem sie verbunden sind, zu verändern. Eine Konstante kann daher ihren einmal zugewiesenen Wert nie wieder ändern; der Wert ist eben konstant. Eine Variable hingegen verändert ihren Wert im Laufe der Zeit. So macht es Sinn, dass der Name Alter eine Variable ist, da alles Existierende bekanntermaßen älter wird. Ein Name, sagen wir Spezie wird sich hingegen nie ändern. Ich zum Beispiel gehöre der Spezie Mensch zu, und somit gilt für mich Spezie = Mensch.
Beiden, Variablen und Konstanten, ist jedoch gemein, dass sie erst deklariert und initialisiert werden müssen, bevor sie benutzt werden. Deklariert bedeutet schlicht, dass sie dem System bekannt gemacht werden. Dazu müssen zwei Dinge angegeben werden:
- Den Namen der Konstanten oder Variablen.
- Den Typ des Wertes, mit dem die Konstante oder Variable verbunden ist.
Mit Initialisierung ist die Tatsache gemeint, dass einer Variablen oder Konstanten ein Wert zugewiesen wird. Diese Wertzuweisung muss nicht zwangsläufig mit der Deklaration gleichzeitig erfolgen. Wichtig ist nur, dass einer Variablen oder Konstanten ein Wert zugewiesen wird, bevor dieser ausgelesen wird.
Hier ein Beispiel für die Deklaration bei gleichzeitiger Initialisierung einer Konstanten name und einer Variablen alter. Doch eines muss ich kurz erklären: In Swift hat man sich darauf geeinigt, dass Namen für Variablen oder Konstanten klein geschrieben werden, unabhängig davon, ob es sich um Nomen, Verben oder Adjektive handelt. Es gibt noch andere Konventionen, die später beschrieben werden. Aber nun wieder zum Beispiel.
let name = "Peter" var age = 42
Eine Deklaration beginnt bei Konstanten mit dem Schlüsselwort let und bei Variablen mit dem Schlüsselwort var, danach folgt der Name. Im oberen Beispiel werden zusätzlich der Konstanten name und der Variablen age jeweils ein Wert zugewiesen; das ist die Initialisierung. Dies erfolgt mit den Gleichzeichen = und dem entsprechenden Wert rechts davon. Das Gleichzeichen drückt somit, anders als in der Mathematik, keine Gleichheit aus. Er weist den Wert rechts vom Gleichzeichen dem Namen links vom Gleichzeichen zu. Für die Gleichheit sind in Swift die Zeichen == und === zuständig. Doch auf diese werde ich später noch eingehen.
Dem aufmerksamen Leser wird vielleicht aufgefallen sein, dass im oberen Beispiel lediglich Namen und Werte in den Deklarationen benutzt werden, jedoch keine Typen. Und dies, obwohl ich zuvor geschrieben habe, dass der Typ einer Variablen oder Konstanten immer angegeben werden muss. Nun, das liegt daran, dass Swift in der Lage ist, den Typ einer Variablen oder Konstanten aus dem zugewiesenen Wert abzuleiten. So ist im oberen Beispiel "Peter" eine Zeichenkette, was bedeutet, das die Konstante name automatisch vom Typ String (Zeichenkette) ist. Die Variable age ist vom Typ Int, was eine Zahl darstellt. Dieses Ableiten nennt sich Type Inference.
Obwohl Swift Type Inference beherrscht und die explizite Typangabe nicht notwendig ist, solange bei der Deklaration ein Wert zugewiesen wird, kann eine Deklaration folgendermaßen aussehen.
let name : String = "Peter" var age : Int = 42
Hier haben wir das gleiche Beispiel, jedoch mit Typangabe (type annotation) und Wertzuweisung. Es sei dem Leser überlassen, zu entscheiden, welche der zwei Varianten ihm besser zusagt. Ich persönlich bevorzuge die explizite Variante. Sie ist meiner Meinung nach nicht schlechter lesbar, zwingt mich dafür, beim Schreiben über den Typ nachzudenken.
Wie aber, sieht eine Deklaration aus, wenn zum Zeitpunkt der Deklaration der Wert noch nicht feststeht, der zugewiesen werden soll? Nun, man lässt schlicht und einfach die Wertzuweisung weg, muss aber dafür zwingend den Typ angeben. Dies ist dann eine Deklaration, jedoch keine Initialisierung.
let name : String var age : Int
Nachdem die Konstanten definiert sind, werden sie in der Funktion print benutzt. Der Ausdruck \(aufgabe) bewirkt, dass der Inhalt der Konstante aufgabe ausgegeben wird. Der Ausdruck \(ergebnis) führt dazu, dass die Zahl 2 ausgegeben wird.
Jetzt könnte man auf die Idee kommen, die Konstante aufgabe mit dem Ausdruck \(ausgabe) auswerten zu lassen und das Ergebnis der Konstanten ergebnis zuzuweisen, so wie im folgenden Beispiel:
// 5. Versuch let aufgabe = "1 + 1" let ergebnis = "\(aufgabe)" print("\(aufgabe) = \(ergebnis)")
Wenn man jetzt das Programm ausführt, erhält man folgende Ausgabe im Konsolenbereich: 1 + 1 = 1 + 1.
Was ist jetzt passiert? Kleiner Tipp: Ist im o.g. Themenblock “Konstanten und Variablen” beschrieben.
Nun, die Konstante aufgabe kann nur Zeichenketten speichern, was wir schlicht durch die Zuweisung von “1 + 1” festgelegt haben. Die Zeile
let ergebnis = "\(aufgabe)"
führt dazu, dass ergebnis nur Zeichenketten speichert. Das liegt daran, dass die Auswertung der Anweisung \(aufgabe) eine Zeichenkette ist.
Ok, halten wir fest: Wir sind in der Lage, Swift mathematische Ausdrücke auswerten zu lassen. Zumindest die vier grundlegenden Operatoren wie Addition, Subtraktion, Multiplikation und Division. Dass noch viel mehr geht, werden wir in den nächsten Blogs sehen.
Kommentare