Die List in Swift UI - Teil 2 - Eine Liste von Personen


Im zweiten Kapitel diese Reihe sollen etwas anspruchsvollere Daten angezeigt werden und gut eignen sich die Informationen zu einer Person. Eine Klasse mit Eigenschaften für Vor- und Nachname wird als Datenmodel für den Anfang genügen. Dazu ein Geburtsdatum und eine Id. Letztere werden wird verwendet, um die Listenelemente eindeutig zu identifizieren. Wie im letzten Kapitel gezeigt ist das, in Verbindung mit einer ForEach-Schleife, erforderlich. Der Typ UUID erzeugt bei der Initialisierung automatisch einen einmaligen Wert und übernimmt somit die Aufgabe.

import Foundation


public class Person {

    let id = UUID()

    var firstName : String = ""

    var lastName : String = ""

    var birthday : Date = Date()

}

Als Datenmodel genügt die Klasse aber es wäre en großer Aufwand, in einer App viele unterschiedliche Personen zu erzeugen. Sämtliche Werte müssten im Programmcode hinterlegt werden. Besser wäre eine Klasse, welche diese Aufgabe übernimmt und Personen mit zufälligen Eigenschaften erzeugt. Ein Art RandomPersonGenerator.

Leider ist es für ein Programm nicht leicht, Namen zu generieren, die nicht aus einer zufälligen Anordnung von Buchstaben bestehen. Die Klasse enthält daher Arrays von Vornamen und Nachnamen, aus der zufällig Einträge gewählt werden. Das schränkt die möglichen Namen zwar ein, die Arrays können aber jederzeit und mit geringem Aufwand erweitert werden. Mit der Funktion randomElement liefert Swift automatisch einen zufälligen Wert aus den Arrays. Etwas aufwändiger ist die Generierung eines zufälligen Geburtsdatums. Aus zwei Daten wird eine TimeInterval gebildet und anschließend ein zufälliger Wert aus diesem Bereich ermittelt.

Die Klasse selbst ist ein Singleton. Das bedeutet, im gesamten Programm existiert nur eine einzige Instanz dieser Klasse. Das ist leicht umzusetzen, indem man die init-Methode der Klasse als private deklariert. Der Zugriff geschieht ausschließlich über shared, einem statischem Feld der Klasse RandomPersonGenerator.

import Foundation


public class RandomPersonGenerator {

    

    static let shared = RandomPersonGenerator()

    private var firstNames = [String]()

    private var lastNames = [String]()

    private let minBirthYear = 1960

    private let maxBirthYear = 2010

    

    private init()

    {

        firstNames.append(contentsOf: ["Rose""Billie""Ben""Ken""Michael""Thomas""Mike""Kenzie"])

        firstNames.append(contentsOf: ["Jane""John""Russel""George""Kagney""Arnold"])

        firstNames.append(contentsOf: ["Bruce""Steve""Patty""Bill""Ted""Peter""David""May""Gwen"])

        lastNames.append(contentsOf: ["Swift""Piper""Steele""Rogers""Stark""Hawkins""Lee""Kirby"] )

        lastNames.append(contentsOf: ["Cambell""Hart""Jordan""Fielding""Crispin","Ford""Jones"])

        lastNames.append(contentsOf: ["Anderson""Reeves""Sagan""Morgan""Parker""Watson"])

    }

    

    private func getRandomDate() -> Date {

        

        var minComponents = DateComponents()

        minComponents.year = self.minBirthYear

        minComponents.month = 1

        minComponents.day = 1

        let minDate = Calendar.current.date(from: minComponents)


        var maxComponents = DateComponents()

        maxComponents.year = self.maxBirthYear

        maxComponents.month = 12

        maxComponents.day = 31

        let maxDate = Calendar.current.date(from: maxComponents)

        

        let span = TimeInterval.random(in: minDate!.timeIntervalSinceNow...maxDate!.timeIntervalSinceNow)

        return Date(timeIntervalSinceNow: span)

    }

            

    public func generate() -> Person {

        let person = Person()

        person.firstName = self.firstNames.randomElement()!

        person.lastName = self.lastNames.randomElement()!

        person.birthday = self.getRandomDate()

        return person

    }    

}

Was jetzt noch fehlt, ist eine Klasse, welche eine Auflistung von Person-Instanzen verwaltet. Sie soll PersonRepository heißen. Als Parameter erhält die init-Methode die Anzahl von Personen, die zufällig erzeugt werden sollen. Werden diese Beispieldaten nicht benötigt, kann eine 0 übergeben werden. Das Repository kann auch Personen verwalten, die nicht mit zufälligen Daten erzeugt wurden.

Die Klasse wird als ObservableObject gekennzeichnet und die Eigenschaft persons als @Published. So wird erreicht, dass sich die View automatisch aktualisiert, wenn dem Repository eine weitere Person hinzugefügt wird, oder eine Person gelöscht wird. Mehr dazu in einem der folgenden Kapitel.

import SwiftUI


public class PersonsRepository : ObservableObject  {


    @Published var persons = [Person]()

    

    init(randomPersonsCount : Int) {

                

        for _ in 0..<randomPersonsCount {

            self.persons.append(RandomPersonGenerator.shared.generate())

        }        

    }

}

Der View, um die Liste der Personen anzuzeigen, ist ebenfalls einfach aufgebaut. Erneut kommt eine ForEach-Schleife zum Einsatz. So können mit nur wenigen Zeilen Programmcode alle Personen aus dem Repository angezeigt werden. In der View wird das Repository als ObservedObject gekennzeichnet. Es wird von der View »beobachtet«. Das funktioniert jedoch nur, wenn die Klasse ein ObservableObject ist. Ein »beobachtbares Objekt«.

import SwiftUI


struct ContentViewView {

    

    @ObservedObject var repo = PersonsRepository(randomPersonsCount: 10)

    

    var body: some View {

        List {

            ForEach(self.repo.persons, id: \.id) { person in

                Text("\(person.firstName) \(person.lastName)").font(.headline)

            }

        }

    }

}

Stacks Image 166

Geschrieben am: 05.07.2021
Technologien: SwiftUI, List