Wir basteln mit SwiftUI, SwiftData und Co. die Fardal App

News-Bote

Ich bring die Post
Wir basteln mit SwiftUI, SwiftData und Co. die Fardal App

fardal-artikelbild.png


Bei Dr. Windows basteln wir häufiger Wochenendprojekte, um einfach einmal gewisse Dinge und Technologien ausprobieren zu können. Die Fardal App ist hier etwas anders. Einerseits ist sie nicht abgeschlossen und zweitens ist es eigentlich mein Day-Job Swift zu entwickeln – oder? Wir basteln uns eine SwiftUI, SwiftData und CoreML Inventur iOS-App!

Überblick und Retrospektive statt Fachveröffentlichung​


All die Basteleien von Dr. Windows sollen aufzeigen, was man alles so machen kann mit moderner Hardware, ohne dabei selbst viel Geld vorab investieren zu müssen. In diesem Falle benötigt ihr nur einen Mac. Aus diesem Grund soll euch diese Artikelreihe einen Überblick über das “Wie” als auch über das “Wie war es?” geben.

Ein tieferer technischer Einstieg in die komplexen Eigenheiten der Frameworks ist nicht geplant. Falls ihr daran Interesse habt, lasst es uns in den Kommentaren wissen!

Vermischung aus Beruf und Hobby?​


Wer mich von euch näher kennt, der weiß, dass ich hauptberuflich “Senior Engineer for B2B and B2E iOS and iPadOS Applications” bin. Ein langer Rollenname, der nicht mehr aussagt, als dass ich seit langer Zeit an mobilen Apps schraube, welche im B2B (Business 2 Business) und im B2E (Business 2 Employee) Umfeld angesiedelt sind. Somit sind dies keine Programme, welche Otto-Normal-Verbraucher nutzt, sondern jene, welche Firmen als Arbeitsmittel nutzen oder an ihre Arbeitnehmer ausrollen.

Diese spannende Tätigkeit bringt jedoch auch mit sich, dass der Fokus nicht immer auf der neusten Technologie liegt. Wartbarkeit, Sicherheit und Kompatibilität werden hierbei verständlicherweise meist einen höheren Stellenwert zugordnet als die Evaluation neuer Techniken, solange es nicht um die Verbesserung von Sicherheit und Datenschutz geht. Aus diesem Grund wollte ich für mich mal ohne Termindruck und anderen störenden Umständen aus der Arbeitswelt in Ruhe mit dem im Titel genannten neuen Technologien von Apple beschäftigten. Angefangen von Swift 5.9 über SwiftUI und SwiftData bis hin zu CoreML – also dem Machine Learning” von Apple.

Mir ging es auch darum, ob es mir als Entwickler, welcher sich seit knapp einer Dekade damit beschäftigt, wirklich so leichtfällt, mich in die neuen Frameworks einzuarbeiten, wie es das Developer-Marketing-Team von Apple sagt.

Fardal? Was heißt das nun wieder?​


Jedes Kind braucht einen Namen. Bei meinen Projekten mache ich mir es meist einfach. Ich schreibe den Begriff, um was es geht, auf Deutsch in den Übersetzer der Wahl und suche mir eine Sprache, in dem das Wort für uns fremd, kurz und prägnant klingt. So war es auch hier nicht anders. Fardal ist eine App, um Dinge eines Sammlers zu erfassen, also eine Inventur zu machen. Somit heißt Fardal nichts anderes als “Inventur” auf walisisch.

Da es bei unseren Basteleien ja nie um ein Produkt handelt, was wir jemals veröffentlichen wollen, überspringe ich hier meist, ob es andere Produkte mit den gleichen Namen gibt – man muss ja nicht alles bitterernst nehmen.

Was ist Fardal?​


Als Nutzungsszenario sieht Fardal die Erfassung von Sammlungen (Collections) vor. Seien es Sticker, Maker-Zubehör, Trading-Cards oder sonstiges. In diesen Sammlungen lassen sich Gegenstände (Items) erfassen. Diese können mit Eigenschaften versehen werden. Weiter soll Fardal ermöglichen, Sammlungen und Gegenstände digital wieder zu finden, indem man beispielsweise eine handschriftliche Notiz abfotografiert, die App es in eine ID umwandelt und diese schlussendlich auf einen Datenbankeintrag filtert.

Das Design​


Kurzum: Es gibt keins. Normalweise mache ich mir vor dem Start eines Projektes immer grobe Notizen, welche Art von Oberflächengestaltung ich gerne hätte. Bei Fardal habe mir ich diesen Schritt erspart, da ich merkte, dass ich erstens keine zündende Idee habe und zweitens wissen wollte, wie ein Standard SwiftUI Projekt aussieht, auf dem man außer Typographie keinen zusätzlichen Aufwand in Richtung Gestaltung betreibt. Ein hoch auf Bastelprojekte, wo man so, frei Schnauze, arbeiten kann!

Dennoch habe ich mich natürlich an eine Stilrichtung und die hierdurch entstehende Vorgabe gehalten, alles ist im “Form”-Stil, was die meisten iOS-Nutzer beispielsweise aus der Systemsteinstellung-App kennen. Dieser bietet eine weitgehend konsistente Oberflächengestaltung an, übernimmt sehr viel an Typographie und wirkt in meinen Augen sehr rund – auch wenn dieser stark limitiert ist, welche Oberflächenkomponenten sinnmachend unterstützt werden.

Begriffe​


Im folgenden Artikel werden Begriffe genannt, welche eine kontextuelle Verortung benötigen.

Eigenschaft, Feld, Property, Variable
Beschreibt eine Eigenschaft eines Objektes wie beispielsweise “rot” wenn das Objekt des Typen Auto ist.

View
Hat mehrere Bedeutungen innerhalb von Swift und SwiftUI, in diesem Beitrag gleichzusetzen mit “Page” oder “Seite” und beschreibt einen Bildschirm in der App. Innerhalb von SwiftUI ist allerdings alles Sichtbare eine View.

Komponente
Ein Bestandteil einer View. Eine View kann aus vielen Komponenten bestehen.

Collection
Ein Name innerhalb der Fardal App, welche eine Sammlung von Items beschreibt.
Beispiel: Raspberry Pis

Item
Ein Name für ein Stück innerhalb einer Collection
Beispiel: Netzteil für Raspberry Pi Micro

Tag
Ein-Wort-Beschreibung für ein Item welcher mehrere Tags haben kann
Beispiele für das oben erwähnte Item: USB-C, Netzteil, Strom

Der Startschuss​


Eine neue iOS-App habe ich – beruflich bedingt – schon des Öfteren angelegt. Immer wieder spannend ist hierbei, wie sich der “File -> New Project”-Wizard in Apples Xcode über die Jahre verändert. Damals, als es das neue Feature von Storyboard gab, haben sich mit der Einführung von Swift auch andere Meilensteine von Apple mit neuen Auswahldialogen und Checkboxen verewigt. Die nun neuen Felder, welche für Fardal interessant sind, sind “SwiftUI” als Interface und “SwiftData” als Storage. Die Applikation ist zwar plattformübergreifend angelegt, wir beschränken uns vorerst jedoch auf die iOS-Ausprägung hiervon.

Da heutzutage ein Projekt nichts mehr ist ohne zusätzlich Build-Tooling – ja, ich schau dich an, JavaScript -, habe ich in diesem Zug auch gleich noch Konfigurationsdateien für SwiftLint und SwiftFormat hinzugefügt, sowie eine Datei, welche die exakte Swift Version enthält, welche dann für die vorher genannten Werkzeuge wichtig ist. Dies ist um so wichtiger, da im Apple-Entwickler-Ökosystem sehr viele Dinge von der macOS Version als auch von der verwendeten Swift-Version beeinflusst werden. Somit ist eine harte Versionierung der Entwicklerwerkzeugkette mittlerweile unerlässlich.

Eingesetzte Techniken​


Fardal basiert auf drei großen Bestandteilen. Angefangen von SwiftUI für die Benutzeroberfläche und State-Management, SwiftData zur Datenpersistenz und CoreML für ein bisschen Machine Learning und “KI”.

SwiftUI​


Das im Jahre 2019 auf der Apple hauseigenen Entwicklerkonferenz WWDC vorgestellte Framework zur deklarativen Oberflächenerstellung von Applikationen wird seitdem Jahr für Jahr erweitert und an etlichen Stellen auch in der Benutzung vereinfacht. Es gilt mittlerweile als der Standard für neuentwickelte Apps.

Zu vergleichen ist es mit Jetpack Compose von Android oder auch von .NET-Applikationen welche ohne *.xaml Dateien pur in C#-Quelltexten entwickelt werden. Denn wie auch dort ist der große Vorteil von SwiftUI, dass Logik als auch Oberfläche in derselben Programmiersprache entwickelt werden.

SwiftData​


Diese speziell für Swift und SwiftUI entwickelter Aufsatz auf dem seit mehreren Dekaden existierenden CoreData Framework wurde 2023 von Apple vorgestellt. Es bringt die Vorzüge von CoreData in eine für Entwickler leichter und sicherer zu verwendende Form auf alle Apple-Plattformen. Hierbei muss erwähnt werden, dass es sich hierbei nicht um eine Verbindung zu einem externen Datenbankserver handelt oder um einen funktionsreichen OR-Mapper.

Core ML / Vision​


Unter dieser Bezeichnung laufen alle Bestrebungen Apples Machine Learning, künstliche Intelligenz und Co für die breite Entwicklerlandschaft verfügbar zu machen. Alle Operationen laufen dabei auf dem Gerät ab und benötigen somit keine Verbindung zum Internet.

Apple stellt eine gewisse Anzahl an vor-trainierten Modellen zur Verfügung, welche in den eigenen Applikationen eingebettet werden können.

Der Aufbau​

FardalApp.swift​


Der Einstiegpunkt einer auf SwiftUI basierenden App ist immer ein Datenobjekt, was von “App” erbt und mit “@main” gekennzeichnet ist. In unserem Fall ist es “FardalApp.swift” (GitHub). In diesem “struct” werden alle programmweiten Abhängigkeiten wie Datenbank, Services und Repositories aufgesetzt. Im Fall von Fardal hängt hier auch das Theming, ob Light- oder Dark-Mode, mit an der View Hierarchie.



Für iOS-Applikationen haben die hierarchischen Abgrenzungen von App zu Scene zu ContentView nur wenig Auswirkung. Diese sind vor allem für macOS und andere Plattformen interessant, welche mehr als ein Fenster erlauben.

ContentView.swift​


In dieser View (GitHub) erzeugen wir den grundlegenden Aufbau der App, welcher bei Fardal eine TabView ist. Unter Android würde man eine solche Komponente in etwa als “BottomBar” bezeichnen. Da man mittels SwiftUI eine Oberfläche nur deklariert und dem System es überlässt, wie es diese auf der entsprechenden Plattform darstellt, ist es wichtig semantisch richtig zu entwickeln. So setzen wir die “Label”-Komponente ein, welche auf iOS ein Icon und einen Titel vertikal anordnet, auf beispielsweise einem iPad jedoch wären sie auf horizontaler Ebene platziert.



Mittels dem “#Preview” Macro erzeugen wir eine Vorschauansicht, um Änderungen direkt sehen zu können. Der äquivalente Begriff aus dem .NET-Ökosystem wäre “Hot Reload”. Eine Art grafischen Designer wie unter Visual Studio gibt es hier nicht.

DashboardView.swift​


Die DashboardView (GitHub) steht als Beispiel für eine mit Inhalten versehene Oberfläche. Die ersten Zeilen des dahinterliegenden Datenobjektes beschreibt den Datenbankzugriff mittels SwiftData. Die “Query”-Annotation ermöglicht es, Informationen aus der eingebetteten Datenbank der App zu laden. Mittel dem “sort” Attribute können wir bestimmen nach welcher Eigenschaft des Datenmodells die Liste sortiert sein soll und mit “order” definieren wir, ob es auf- oder absteigend angeordnet wird. Dieser Datenbankzugriff ist nur möglich, da wir in der FardalApp.swift den “modelContainer” definiert haben und App-weit verfügbar gemacht haben.

Den SwiftData-basierenden Feldern folgen sogenannte “@State”-Properties. Diese sind Variablen, welche innerhalb des SwiftUI State-Managers existieren können. Einfach ausgedrückt behalten diese ihren Zustand, auch wenn die Oberfläche neu generiert wird, und lösen bei Änderung deren selbst ein neues Erstellen der UI-Bestandteile aus in welchen sie Verwendung finden. Hierbei handelt es sich beispielsweise um ein boolsches Flag, welches anzeigt, ob gewisse Alerts oder Overlays angezeigt werden sollen. Das vom “View”-Protokoll verpflichtende Feld “body” beinhaltet die initial geladene Oberfläche, welche beim Verwenden der View oder auch der Komponente angezeigt wird.

Als oberstes Element habe ich mich für einen NavigationStack entschieden. Dieser defacto Nachfolger einer NavigationView ermöglicht es, in andere Ansichten abzuspringen und unter anderem einen Titel mittels dem Modifier “.navigationTitle()” der View (in diesem Falle der Page) zu setzen.



Innerhalb des NavigationStacks habe ich mich für eine Form-Komponente entschieden, um ein einheitliches Erscheinungsbild der App zur gewährleisten, ohne mich groß daran kümmern zu müssen. Damit meine “Form”-Komponente nicht unnötig aufgebläht wird, habe ich mich entschlossen, dessen Inhalte in eigene Methoden auszulagern. Diese so genannten “ViewBuilder” helfen dabei, Quelltext besser zu strukturieren und eventuell innerhalb der View auch wieder zu verwenden.

So erstellt die Methode “makeCollectionsSection()” eine neue Sektion für unser Form, in welcher, insofern die Datenliste der Collections leer ist, ein Tipp angezeigt wird oder durch eine ForEach()-Schleife Thumbnails, welche eine separate View ist, der letzten zehn Collections angezeigt werden. In der Kopfzeile dieser Sektion befindet sich am rechten, äußeren Rand ein “Plus”-Button, um eine neue Collection anzulegen. Dieser ist mit einem NavigationLink versehen, welcher dank des NavigationStacks ermöglicht. in die “Neue Collection”-Ansicht zu springen.

CameraModel.swift​


Fardal nutzt CoreML, um Bilder und Schriften zu erkennen. Dies geschieht in der Klasse CameraModel (GitHub). Diese ist ein Wrapper rund um die aus AVFoundation stammende AVCaptureSession und ermöglicht die Nutzung der Kamera des iPhones für Bilder, aber auch um Tags erstellen zu können oder handschriftliche Texte als eine Hilfe bei der Suche verwenden zu können.

Interessant für CoreML ist hierbei die Methode “classifyImage()”, welche auf Basis eines geschossenen Fotos versucht, dort enthaltene Objekte zu erkennen und diese als Tags zurückzugeben. Dies geschieht maßgeblich mit der vom ML-Model zur Verfügung gestellten Funktion “classifier.prediction()”. Als Rückgabewert erhalten wir von dieser eine Liste von erkannten Objekten inklusive eines Prozentwertes, wie sicher sich hierbei das Model fühlt. Je höher, um so sicherer ist es sich, dass es sich wirklich darum handelt. Ob dies der Realität entspricht, hängt vor allem von der Größe des Models ab. Kleine Modelle neigen dazu, weniger Objekte zu erkennen, diese zu verallgemeinern oder einfach falsch zu liegen, obwohl der Prozentsatz, wie sicher sich das Model ist, hoch ist.



Da AVFoundation und Co noch nicht an das Swift-Ökosystem angepasst sind, müssen hier Entwicklungsmuster verwendet werden, welche aus UIKit Zeiten noch bekannt sind.

Resultat​


In der version 0.0.x schaut Fardal wie folgt auf den einzelnen Views aus.

Mein gespaltenes Fazit​


Es kommt mir vor, als ob ich in all meinen letzten Beiträgen über die Softwarequalität der Big-4 jammere und mich manchmal auch dabei erwische, wie ich mich aufrege. So ist es hier ebenfalls wieder. Angemerkt sei, dass diese Erfahrungen nicht von zwei Stunden Bastelei am Wochenende stammen, sondern von 40 Stunden die Woche permanenter Nutzung– zumindest bei Xcode.

Xcode & Simulator​


Nach jedem Update habe ich die Sorge, dass irgendetwas nicht mehr funktioniert. Kürzlich war für etliche Versionen im Simulator die Settings-App defekt und stürzte ab, oder Xcode cached gefundene Fehler, zeigt diese an, obwohl sie schon längst behoben sind und der Build erfolgreich durchläuft. Für letzteres gibt es “nun” den Menüeintrag “Alle Fehlermeldungen leeren” – dieser wird häufiger benutzt als mir recht ist.

In meinem Alltag in meinen B2B-Programmen fallen viele Fehler gar nicht erst auf, da, wie erwähnt, diese auf altbewerter Technologie wie UIKit basieren. Bei der Nutzung neuerer Frameworks oder Targets wie Home-Screen-Widgets schmerzt die Benutzung gefühlt sehr. Wer sich also wundert, warum beispielsweise auf dem Simulator keine eigenen Widgets angezeigt werden, es liegt nicht an eurem Quelltext, sondern am Simulator. Auf einem realen Gerät funktioniert es wie gewollt.

Da sind wir auch beim Kern des Ganzen. Xcode macht mir so viel Spaß, wenn es funktioniert. Es ist schnell, übersichtlich und nicht überladen. Man macht schnell Fortschritte und viele neuen Funktionen wie String Kataloge sind Gold wert! Nachdem JetBrains ihre AppCode-IDE im letzten Jahr leider eingestellt haben, gibt es hierzu keine Alternative mehr. Der defacto Nachfolger JetBrains Fleet bietet hierfür noch keine ausreichende Unterstützung.

SwiftUI​


Ja, das ist die Zukunft, wie man deklarativ im Apple Ökosystem mit Swift Benutzeroberflächen beschreiben wird! Ja, mit etwas Gewöhnung kann kommt man schnell voran, vor allem, wenn man iOS-nahe Interfaces erzielen möchte. Da SwiftUI nun schon seit etlicher Zeit auf dem Markt ist, hat es mich gewundert, wie oft man noch auf das darunter lebende UIKit zugreifen muss, um gewünschte Effekte oder Grundfunktionalitäten zu erreichen. So bringt SwftUI weder eine WebView, noch eine Kartenansicht mit gruppierten Pins mit sich. Einer der Hauptvorteile ist die Live-Preview der View in Xcode gleich neben dem Quelltext, welche die Ansicht beschreibt. Falls diese denn geht oder nicht immer wieder abstürzt.

Eins darf man nicht vergessen: SwiftUI ist nicht nur bloße Oberfläche, es beinhaltet auch ein ausgewachsenen State-Management sowie ein Concurrency -Feature, welches sich wirklich wie zu Hause anfühlt. Andere Abhängigkeiten wie RxSwift, welche früher das selbige versuchten, fühlten sich in meinen Augen immer etwas wie Fremdkörper an.

SwiftData​


Das Framework hat eine Lernkurve, welcher man gewachsen sein muss. Mir persönlich ist es noch nicht gelungen, diese zu meistern. Vor allem bei 1:n- und n:n-Beziehungen ist mein Wissen als auch das Verhalten der App noch stark fehleranfällig. Dabei fällt es mir schwer, oft den Nutzen des Frameworks zu sehen, wenn man nicht mit tausenden an Objekten hantiert. Funktionen, die ich aus anderen Datenbank-Umgebungen gewohnt bin, wie die Suche via einer ID eines Objektes, sind nicht verfügbar, oft stürzt die App ab und der Debugger landet in einem Swift-Data Property Macro, welches keinerlei Informationen gibt, wieso es an dieser Stelle abgebrochen hat, und für mich am Verwirrensten ist, wie man SwiftData überhaupt einsetzen sollte. Als reine DTO-Schicht oder doch als Business-Model oder eine Mischung aus beiden? Ich bin hier noch auf einer langen und wohl auch Kopfschmerz-bereitenden Reise.

CoreML​


Es ist spannend zu sehen, mit wie wenig Arbeit man heutzutage in die Welt des Machine-Learnings beziehungsweise in dessen Resultate eintauchen kann. Vor allem die Handschrifterkennung hat mich in Staunen versetzt. Andererseits war ich überrascht, mit wie viel Handarbeit man beispielsweise mit der Objekterkennung zu tun hat. Solche Low-Level-Konvertierungen erhoffte ich mir als Systemfunktion. Ebenso, dass die Objekterkennung mit dem vom Apple bereitgestellten Model nur englische Wörter ausspuckt und iOS beziehungsweise Apple kein Framework bereitstellt um diese zu übersetzten – vor allem, weil auf modernen iOS-Geräten eine Übersetzungs-App vorinstalliert ist.

Dennoch zufrieden​


Jetzt, mit etwas Abstand, kann ich dennoch sagen, dass ich positiv überrascht bin, wie alles in sich greift. Man sollte als alter iOS-Entwickler auch einfach sich öffnen und versuchen, die alten Paradigmen und Entwicklungsmuster abzulegen und eine neue Denkweise zu akzeptieren. Die Abstürze in Xcode sind und bleiben ärgerlich, dass der iOS-Simulator in einem oft nicht guten Zustand ist, okay, ungut, aber damit muss man umgehen können. Ein Android-Emulator weist genau so seine Probleme auf wie ein Visual Studio unter Windows. Moderne Programme und Frameworks sind so komplex geworden, dass man diese Fehlerfreiheit, wie man sie vor zehn Jahren kannte, nicht mehr erwarten kann – leider.

Dass CoreML unzureichende Ergebnisse liefert, liegt weniger am Framework, sondern eher am Model, was dahinter liegt, und eventuell können größere Modelle auch mehr Sprachen. Einzig und allein SwiftData bleibt bei mir noch auf der Liste, wo ich noch nicht wirklich überzeugt bin, ob es einen Mehrwert bietet. Entweder sind die Apps zu klein und ein einfaches JSON auf der Platte des iPhones reicht aus, oder es ist zu komplex und man braucht einen großen OR-Manager.

Es bleibt also spannend, und das ist auch gut so!

Ausblick​


Generell bleibt Fardal erhalten, um weiterhin als Spielwiese für mich außerhalb meines beruflichen Alltags zu dienen. Aus diesem Grund möchte weiter versuchen, SwiftData besser zu verstehen und dessen Denkweise zu verinnerlichen oder hinter noch offene Mysterien von SwiftUI zu steigen. Ebenso möchte ich neue Oberflächen ausprobieren. Eine Einführung von Widgets ist geplant, eine bessere Suche oder angepasste Oberflächen für andere Apple Plattformen wie macOS oder iPadOS stehen auch noch auf der Liste.

Allerdings ist mein Urlaub nun zu Ende und ich bin zurück in meinem beruflichen Entwickleralltag. Das Schöne an Basteleien ist, dass dies vollkommen in Ordnung ist und man weiter macht, wenn man dafür Zeit, Lust und Laune hat.

Habt ihr Interesse an diesem Thema? Was würde euch interessieren? Lasst es uns in den Kommentaren wissen!

zum Artikel...
 
Oben