Entwicklertagebuch: Kennzeichner #5: Die iOS-App

Im vorigen Teil dieser kleinen Serie haben wir eine allererste Version der Android-App des Kennzeichners (GitHub) erstellt. Nun folgt in diesem Teil das Gegenstück für iOS. Hier stellt sich die große Frage, wie sehr sich der in Kotlin geschriebene Kern mit der in Swift und SwiftUI zu schreibenden iPhone App verträgt.
Für alle, denen diese Artikelreihe noch unbekannt ist – das habt ihr bislang verpasst, könnt euch aber natürlich nachträglich einlesen:
- Entwicklertagebuch: #1 mit Bing AI Chat als Datengrundlage
- Entwicklertagebuch Kennzeichner #2: Excel kann Geografie und mag kein Berlin
- Entwicklertagebuch Kennzeichner #3: Shared Core – Der Kern des Ganzen
- Entwicklertagebuch Kennzeichner #4: Jetzt wird’s mobile!
- (Aktuell) Entwicklertagebuch Kennzeichner #5: Die iOS-App
Wieso iOS erst zum Schluss?
Hierfür gibt es mehrere Gründe. Erstens benötigte ich eine App, um den Shared-Core zu testen. Etwaige Unit-Test hätten natürlich auch funktioniert, aber mich trieb die Neugier, mehr mit Kotlin und den Werkzeugen wie Android Studio außen herumzuexperimentieren und mir ein gewisses Gefühl für die Sprache bilden zu können.
Andererseits gab es in den vergangenen Monaten, mit dem Ausblick auf iOS 17 und Swift 5.9 und vor allem mit all den Auswirkungen, welche diese inzwischen veröffentlichten Versionen für das Entwicklerleben mit sich bringen, reichlich Umtriebe in der Swift-Community, insbesondere im Hinblick auf Software-Architektur und Pattern für moderne Swift (UI) Apps.
Für mich persönlich nicht zu vergessen ist, dass ich mit iOS- und iPadOS Apps mein tägliches Brot verdiene. Dies bedeutet auch, dass jeder Quelltext, den ich in meiner Freizeit schreibe, (zu Unrecht) als Qualitätsmerkmal meiner Arbeit oder sogar meines Arbeitgebers herangezogen werden kann. In meinen Augen ist hier jedoch ein großer Unterschied zu machen zwischen “Spaß-” und “professionellem” Code, den ich produziere. Eventuell überreagiere ich hier auch etwas – ich hoffe es!
Hinweis: Produktnamen haben sich verändert
Im Laufe der Kennzeichner-Reihe hat JetBrains, die Macher hinter diesem Shared-Core-Ansatz, die Bezeichnung der Produkte, in Respektive der Technologien, geändert.
KMM (Kotlin Multiplatform Mobile) wurde nun mit Hinblick auf die Unterstützung von Desktop- als auch Web-Targets zu KMP (Kotlin Multiplatform) umbenannt. Hierzu wurde ein erklärender Artikel seitens JetBrain verfasst.
Die Abkürzung CMP für “Compose Multiplatform” wird meistens nicht mehr verwendet, da mit dieser Kurzform auch die Bestandteile “Common Multiplatform” und “Client Multiplatform” von KMP gemeint sein könnten.
Es wird wohl noch etwas Zeit vergehen, bis auch alle Einträge im Internet mit den neuen Namen versehen wurden – dennoch tut JetBrains gut daran, Ordnung in ihr Namensschema zu bringen.
Achtung: Gefährliches Halbwissen voraus
Ich möchte noch einmal klar erwähnen, dass alles, was jetzt folgt, nicht auf die Goldwaage gelegt werden sollte. Ich habe trotz etlicher Bemühungen noch starke und eventuell unbekannte Wissenslücken. Somit können Ansichten und Aussagen nicht der technischen Realität entsprechen.
Im gleichen Atemzug sei auch erwähnt, dass ich mich über jegliche Richtigstellung von Fakten freue und gern mein Wissen weiter ausbauen möchte, was in Richtung KMM geht.
Technologieauswahl
Swift
Wir brauchen nicht mehr zu diskutieren, ob man im Jahre 2023 neue Projekte noch mit Objective-C starten sollte. Jedoch sollten wir darüber reden, mit welcher Swift-Version man neue Apps aufbauen sollte. Anders als in der sonst üblichen semantischen Versionierung existieren bei Swift auch zwischen sogenannten “Dot-Releases”, also beispielsweise von Swift 5.5 auf Swift 5.9, Inkompatibilitäten zwischen den Releases. Nicht zu vernachlässigen ist, dass diese kleineren Versionssprünge auch mehr Hilfe bereitstellen, den bisherigen Quelltext besser zu strukturieren. Ein Beispiel hierfür ist die mit Swift 5.9 eingeführte Möglichkeit, eigene (Compiler-) Makros zu schreiben, um Boilerplate-Code zu reduzieren.
SwiftUI
Ähnlich wie bei Android gibt es auch aus dem Cupertino Lager zwei Wege, eine App-Oberfläche zu entwickeln. Einerseits mit dem altbekannten und seit Dekaden bewährten UIKit inklusive dessen Interface Builders, Storyboards, *.xib-Files, IBOutlets und IBActions. Auf der anderen Seite das seit einigen Jahren immer mehr ausgebaute SwiftUI, welches ähnlich wie Jetpack Compose eine Oberfläche mittels der selbigen Programmiersprache deklariert, die auch sonst in der Entwicklung verwendet wird – sprich Swift beziehungsweise Kotlin für Jetpack Compose.
Auch wenn in meinen Augen SwiftUI trotz all der Jahre noch nicht dieselben Funktionen aufweist wie UIKit, ist das neue Framework meine erste Wahl, wenn es um neue Applikationen für das Apple-Ökosystem geht.
Erzwungene Abhängigkeiten
Ich als Senior Software Engineer, der meistens Applikationen für den B2B-Einsatz entwickelt, versuche externe Abhängigkeiten stets so gering wie möglich zu halten. Für mich stellen sie ein hohes Risiko dar, dass die Applikation in Zukunft nicht mehr wartbar ist. Sei es, dass die Lizenzen der Dependency (und deren Abhängigkeiten) nicht im Kontext der App benutzbar sind oder ganz einfach, dass ich von anderen Entwicklern abhängig bin, ohne mit diesen eine Geschäftsbeziehung einzugehen. Mit dem Blick eines Android- oder Webentwicklers dürfte der folgende Punkt wohl leichter zu verschmerzen sein.
Um halbwegs vernünftig mit dem Shared-Core nebenläufig (Concurrency, async await) arbeiten zu können, wird meist die von Dritten entwickelte Bibliothek KMP-NativeCoroutines verwendet. Auch wenn diese De-Facto-Standard-Dependency wohl wirklich gut ist, ist es eben nichts, was mit KMM direkt mitgeliefert wird. Weiter bringt KMP-NC auch eine Menge an internen Abhängigkeiten mit, welche in vielen Szenarien nicht gebraucht werden. Hierfür in Enterprises eine Sicherheitsfreigabe zu bekommen, stelle ich mir sehr langwierig vor.
Java im Build Prozess
Der Shared-Core ist in Kotlin entwickelt und läuft somit auf der JVM – insofern nichts Neues. Aus diesem Grund hat der Kennzeichner als eine extra Build-Phase, bevor überhaupt die App gebaut wird, einen Gradle-Aufruf, um den Shared-Core neu zu bauen. Falls wir den Shared-Core als normale Dependency eingebunden hätten ,welche über CocoaPods verwaltet wird, könnte dieser Schritt entfallen, wir würden uns dafür einen komplett anderen Schuh anziehen.
Mint zur Build-Tooling Verwaltung
Als Entwickler hat man oft den Bedarf, dass beim Bauen der Applikation mehr passiert als nur ein wenig Kompilierung. Im Beispiel des Kennzeichners ist es neben dem Bau des Shared-Cores auch das Formatieren von Quelltext als auch das sogenannte “linten”, also aufzeigen, dass gewisse Regeln im Sinne von “so benutzen wir es nicht” dem Entwickler in der Entwicklungsumgebung angezeigt werden. Mint hilft hier, alle Versionen der eingesetzten Helferlein zentral zu platzieren und immer wiederherstellbar auf anderen Rechnern einzurichten.
Ein Learning ist, dass das “Pro Build auch Quelltext formatieren” mit SwiftUI Previews sehr schlecht funktioniert und die Entwicklungsgeschwindigkeit reduziert.
Entwicklung
AppStore.swift
Zumindests mit dem Stand meines KMP-Stacks ist es relativ schwer, den Shared-Core, welcher perfekt in Android funktioniert, genauso schmerzfrei auch unter iOS und Swift verwenden zu können. Hier kommt der Fakt zu tragen, dass JetBrains den Shared-Core nach Objective-C und nicht nach dem modernen Swift transpiled.
Darum habe ich mich entschlossen, vorerst alle Zugriffe auf den Shared-Core in einem Wrapper namens “AppStore.swift zu bündeln und somit nur diesen als sogenanntes SwiftUI typisches EnvironmentObject, also über die Dependency Injection, in der iOS-App weiterzuverwenden.
ContentView.swift
Der AppStore regelt auch, in welchem Status sich eine App befindet. Ob noch keine Daten vorhanden sind, ob Daten geladen worden oder es fehlgeschlagen ist. Darauf können wieder Views, wie in diesem Falle die in der Hierarchie gesehen oberste ContentView.swift, hören und entsprechende Oberflächenelemente darstellen. In dem unten aufgeführten Quelltextbeispiel ist gut die in Swift 5.9 eingeführte if switch Funktionalität zu sehen.
RegionGridItem.swift
Eine klare Erleichterung gegenüber Android war die einfache Einbindung eines Kartenausschnittes. Keinerlei Ärger mit API-Token und wie man diese erstellt, kein Wrapper in Composables, es funktionierte einfach. Wären hier nicht Änderungen von iOS 16 zu iOS 17 im SwiftUI-Syntax, was die Erstellung von Annotationen, also den Pins auf der Karte, wieder komplett über den Haufen geworfen hat.
Dennoch ist diese Klasse sehr übersichtlich und einfach zu verstehen, da keine komplexe Kartenlogik nötig ist.
Ich musste explizit die Schriftfarbe setzen, da es sonst im Dark-Mode auf Weiß springen würde. In meinem Fall wollte ich allerdings, dass es immer schwarz ist, um gut auf dem gelben Hintergrund sichtbar zu sein und die ferne Illusion eines Städteschildes zu wahren.
Erstes Fazit zu KMP
Ich finde toll, wie viel Energie und Kompetenz JetBrains und die Kotlin Community in das ganze Thema Multiplatform stecken. Ich wünsche mir wirklich, dass es langfristig Erfolg haben wird. Für mich hängt viel daran, wie treu sie ihrer Roadmap bleiben, um vor allem das Zusammenspiel mit iOS zu verbessern.
Gute Chancen haben sie. Vor allem nach dem Aus von Visual Studio for Mac sind zumindest für mich Xamarin und .NET MAUI Geschichte. Flutter erinnert zu sehr an TypeScript und Co. und ist eventuell doch zu klein, um damit vor allem im B2B Kontext etwas anfangen zu können und wollen.
Da Microsoft neben Visual Studio for Mac auch das Surface Duo gekillt hat, ist für mich die (Entwickler-)Lust für Android-Apps erst einmal erstickt worden. Ohne einen wirklichen Grund dafür bin ich mir unschlüssig, ob mein nächstes Pet-Projekt wieder KMP wird oder schlussendlich direkt für die spezifische Plattform nativ entwickelt wird. Die Zeit wird es zeigen.
Kommende Schritte
Hier ist erst einmal Schluss. Nicht, weil ich keine Lust habe und mich all das abgeschreckt hatte, KMP weiterzuverfolgen, sondern weil JetBrains eine sehr optimistische Roadmap vorgestellt hat, wie es mit KMP weitergehen soll. Viele Punkte, wie beispielsweise meine Probleme mit der Objective-C Bridge, welche dann nach Swift verwandeln soll, sind auf dieser Liste enthalten. Somit warte ich lieber und genieße dann das schöne KMP, vor allem im Zusammenspiel mit SwiftUI.
Andererseits ist die iOS-App auf keinen Fall fehlerfrei und der eine oder andere wird wohl auch auf den Bildschirmfotos schon Bugs gefunden haben. Diese werde ich wohl nach und nach angehen, um mein Gespür, wie man Dinge in SwiftUI implementieren muss, weiter auszubauen.
Welche Funktion würdet ihr gern im Kennzeichner sehen? Wie kann man euch, falls ihr auch mit der Android App-Entwicklung beginnen wollt, die Berührungsängste mit dieser Thematik nehmen? Lasst es mich wissen, entweder in den Kommentaren oder mailt mir an tobias@drwindows.de.
Der gesamte Quelltext liegt wie immer auf GitHub offen für jede/n bereit! Lasst uns weiterhin gemeinsam dieses spannende Bastelprojekt weiterführen. Auf das nächste Dutzend! Vielen Dank für euer stetes Interesse.
Thema:
- Entwicklung
Über den Autor

Tobias Scholze
Bayrischer Open Source- und Community-Enthusiast, Verfechter des neuen Microsoft und Wandler zwischen den Betriebssystemwelten. #communityrocks Von Herzen ein Nerd mit der festen Überzeugung, dass man gemeinsam und durch den Einsatz von moderner IT die Welt für jeden ein Stückchen besser machen kann.