Ich hatte das Problem, dass sich die Liste schlichtweg nicht aktualisiert hat. Alle Versuche die Liste dazu zu bringen, sich zu verändern, wenn sich ein Wert des Arrays ändert, führte leider nicht zum Erfolg. Auch ein kompletter Reload des Arrays war nicht zielführend. Für die SwiftUI List habe ich diese Klasse ListDataSource als Observerable Object eingerichtet. Eigentlich hätte sich die Liste bei Änderung eines Wertes im Array ListOfListEntries automatisch alles ändern müssen, also ein Refresh hätte stattfinden sollen. Dem war aber nicht so. Nach langem Suchen war es nur eine Kleinigkeit – nämlich das @Published hat gefehlt. Ich hoffe denjenigen damit geholfen zu haben, die sich damit auch gerade die Finger „brechen“.
class ListDataSource: ObservableObject {
//Nicht mehr erforderlich?
//let didChange = PassthroughSubject()
let didChange = PassthroughSubject()
@Published var ListOfListEntries = [oListEntryFields]() //{
//didSet { didChange.send() }
//}
var ListOfGroups = [oListGroups]()
let oListoryParser = ListoryXMLParser()
let defaults = UserDefaults.standard
var ActiveListKey : String = ""
var ActiveGroupKey : String = ""
var ActiveListTitle : String = ""
var ActiveGroupTitle : String = ""
init() {
reload()
didChange.send()
}
}
…das ist nun wirklich keine Raketenwissenschaft. Den aktuellen Wert hinterlegt man as String – direkte Texteingabe oder halt eine Variable. Die Eigenschaft Text findest Du dann der @State Variable $name wieder. Mit Hilfe der textfieldStyle Eigenschaft RoundedBorderTextFieldStyle() sieht die Textbox so aus, wie wir das aus den Storyboard-Zeiten kennen. Natürlich gibt es zahlreiche Möglichkeiten das Erscheinungsbild des TextField Objekts wunschgemäß anzupassen.
struct ContentView: View {
@State private var name: String = "Peter"
var body: some View {
VStack {
TextField("Enter your name", text: $name)
.textFieldStyle(RoundedBorderTextFieldStyle())
Text("Hello, \(name)!")
}
}
}
Hier eine einfache Funktion mit der Du ein Date in ein deutsches Datumsformat als Stirng konvertieren kannst. Das in deutschland übliche Format sieht so aus: „dd.MM.yyyy hh:mm:ss“
Natürlich kannst Du das auch durch andere Formate prolbemlos ersetzen.
public static func ConvertDateToGermanFormat(DateValue: Date) - String {
let df = DateFormatter()
//Nun legen wir das in Deutschland übliche Format fest
df.dateFormat = "dd.MM.yyyy hh:mm:ss"
//aus dem Date erzeugen wir wiederum ein String
let sNewDateFormat = df.string(from: DateValue)
return sNewDateFormat
}
Gibt nur das Datum im lokalen Format je nach Nutzer einstellung aus. Das Ergebnis kann wie folgt aussehen: “12/31/2019”
let today = Date()
let formatter1 = DateFormatter()
formatter1.dateStyle = .short
print(formatter1.string(from: today))
Hier die Ausgabe von Datum und Uhrzeit abhängig von den regionalen Einstellungen: Das Ergebnis kann so aussehen: “20:27:32” or “8:27:32pm”
let formatter2 = DateFormatter()
formatter2.timeStyle = .medium
print(formatter2.string(from: today))
Hier ein paar fertige Datumsfunktionen in einer Klasse:
class Tools {
public static func ConvertDateToGermanFormat(DateValue: Date) -> String {
let df = DateFormatter()
//Nun legen wir das in Deutschland übliche Format fest
df.dateFormat = "dd.MM.yyyy HH:mm:ss"
//aus dem Date erzeugen wir wiederum ein String
let sNewDateFormat = df.string(from: DateValue)
return sNewDateFormat
}
public static func ConvertDateOnlyFormat(DateValue: Date) -> String {
let df = DateFormatter()
//Nun legen wir das in Deutschland übliche Format fest
df.dateFormat = "dd.MM.yyyy"
//aus dem Date erzeugen wir wiederum ein String
let sNewDateFormat = df.string(from: DateValue)
return sNewDateFormat
}
public static func ConvertDateToLocalFormat(DateValue: Date) -> String {
let formatter = DateFormatter()
formatter.timeStyle = .medium
return formatter.string(from: DateValue)
}
public static func ConvertDateToLocalDateOnlyFormat(DateValue: Date) -> String {
let formatter = DateFormatter()
formatter.dateStyle = .medium
return formatter.string(from: DateValue)
}
public static func ConvertStringToDate(DateValue: String) -> Date {
let formatter = DateFormatter()
let dValue = DateValue
//formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
var date = formatter.date(from: dValue)
if (date==nil)
{
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
date = formatter.date(from: dValue)
}
return date!
}
}
Das passende Datumsformat habe ich hier fix in den Code gesetzt – das kannst Du natürlich auch noch hübscher machen.
class Tools {
public static func ConvertStringToDate(DateValue: String) -> Date {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let date = formatter.date(from: DateValue)
return date!
}
}
Hier ein Praxisbeispiel. Der String Wert befindet sich in der auskommentierten Zeile. In diesem Beipsiel ging es darum, ein XML-File von einem Websearver auszulesen und ein Wiedervorlagedatum in das richtige Date Format zu bringen. Spätestens beim Debuggen erkennt man das vorliegende Format oder man schaut sich das XML-File einfach online an.
//s["Wiedervorlage"] String? "2020-02-09T15:24:21.693+01:00"
let dDate :Date = Tools.ConvertStringToDate(DateValue: s["Wiedervorlage"]!)
Das Setzen des Gebietsschemas auf en_US_POSIX wird beim Parsen von Daten von einem Server dringend empfohlen, um Probleme mit den lokalen Einstellungen des Geräts zu vermeiden. Für einige Hintergrundinformationen darüber gibt bei den TECH NOTES von Apple.
formatter.locale = Locale(identifier: "en_US")
formatter.dateStyle = .short
formatter.string(from: date) // returns 12/10/2018
//Als Beispiel UK
formatter.locale = Locale(identifier: "en_GB")
formatter.string(from: date) // returns 10/12/18
//Man beachte das zweistellige Jahr
//...wenn wir in Deutschland sind...
formatter.locale = Locale(identifier: "de_DE")
formatter.string(from: date) // returns 10.12.18
Turns out the periods are the accepted standard. In addition, DateFormatter has already translated names for you, so you don't have to worry about it:
//...oder aber in Spanien
formatter.locale = Locale(identifier: "es_ES")
formatter.dateStyle = .long
formatter.string(from: date) // returns "10 de diciembre, 2018"
Mit UserDefaults kannst Du jeden beliebigen Basisdatentyp so lange speichern, wie die Anwendung installiert ist. Sie können grundlegende Typen wie Bool, Float, Double, Int, String oder URL schreiben, aber auch komplexere Typen wie Arrays, Wörterbücher und Datum – und sogar Datenwerte.
Wenn Sie Daten in UserDefaults schreiben, werden diese automatisch geladen, wenn Ihre Anwendung ausgeführt wird, so dass Sie sie wieder zurücklesen können. Das macht die Benutzung wirklich einfach, aber Sie müssen wissen, dass es eine schlechte Idee ist, viele Daten darin zu speichern, weil es das Laden Ihrer Anwendung verlangsamt. Wenn Sie glauben, dass Ihre gespeicherten Daten mehr als sagen wir 100KB benötigen würden, ist UserDefaults mit ziemlicher Sicherheit die falsche Wahl.
Bevor wir mit der Modifizierung von Projekt 10 beginnen, werden wir zunächst ein wenig Testkodierung durchführen, um auszuprobieren, was UserDefaults uns erlaubt. Vielleicht finden Sie es nützlich, ein neues Single View App-Projekt zu erstellen, nur um den Code zu testen.
Um mit UserDefaults zu beginnen, erstellst Du eine neue Instanz der Klasse:
Hier zeige ich Dir, wie du mit Swift UI eine Liste generierst. Zuerst laden wir ein XML-File aus dem Web. Dann durchlaufen wir das Array und füllen eine neue DataSource Class mit einem identifiable struct. Wir achten darauf, dass wir nicht @State verwenden, sondern @ObservedObject. Die DataSource class hat den Typ ObservableObject. Für die Liste gibt es ein eigenes Struct, das macht die ganze sache übersichtlicher. Ich selber habe den Fehler als Swift UI Neuling hier @State zu verwenden. Bei dem Versuch die Datenquelle zu füllen, bekam ich keine Fehlermeldung, aber die Anzahl der Datensätze aus dem gelesenen XML-File blieb schlichtweg 0.
Hierfür ein Swift-File anlegen. Das ist die Klasse um XML zu parsen.
Dann legen wir noch ein SwiftUI File ein und definieren hier das struct für die Datenquelle.
Grundlage für die Datenquelle:
import SwiftUI
struct oListEntryFields: Identifiable {
var id = UUID()
var rowID : Int64
var ListKey : String
var ListenGruppenKey : String
var ListenKeyView : String
var Caption: String
}
Hier bewegen wir uns nun im ContentView.swift File. Hier findet man dann auch die Klasse für die Datenquelle.
import SwiftUI
import Combine
class ListDataSource: ObservableObject {
var ListOfListEntries = [oListEntryFields]()
let oListoryParser = ListoryXMLParser()
init() {
oListoryParser.dictionaryKeys.removeAll()
oListoryParser.dictionaryKeys.append("ID");
oListoryParser.dictionaryKeys.append("ListenKey");
oListoryParser.dictionaryKeys.append("ListenGruppenKey");
oListoryParser.dictionaryKeys.append("ListenKeyView");
oListoryParser.dictionaryKeys.append("Bezeichnung");
oListoryParser.dictionaryKeys.append("Aenderungsdatum");
oListoryParser.dictionaryKeys.append("Erstanlagedatum");
oListoryParser.dictionaryKeys.append("Archiviert");
oListoryParser.dictionaryKeys.append("Wiedervorlage");
oListoryParser.beginParsing(tablename: "key", criterion: "bsCQ2ivUHXOyk")
var iRow = -1
for s in oListoryParser.results! {
iRow += 1
let rowID = Int64(s["ID"]!)
let ListEntry = oListEntryFields(rowID: rowID!, ListKey: s["ListenKey"]!, ListenGruppenKey: s["ListenGruppenKey"]!, ListenKeyView: s["ListenKeyView"]!, Caption: s["Bezeichnung"]!)
//LoadListData.append(ListEntry)
ListOfListEntries.append(ListEntry)
}
}
}
public struct ContentView: View {
@State var selection: Int = 0
let defaults = UserDefaults.standard
public var body: some View {
TabView(selection: $selection){
VStack{
ListoryListView()
}
.tabItem {
VStack {
Image("first")
Text("First")
}
}
.tag(0)
Text("Second View")
.font(.title)
.tabItem {
VStack {
Image("second")
Text("Second")
}
}
.tag(1)
}.onAppear(){
}
}
struct ListoryListView: View {
@ObservedObject var oListDatasource = ListDataSource()
let oListoryParser = ListoryXMLParser()
@State var selection = Set()
var body: some View {
NavigationView {
List(){
ForEach(oListDatasource.ListOfListEntries)
{ item in
VStack(alignment: .leading){
Text(item.Caption)
}
.onTapGesture {
print("\(item.Caption)")
}
.navigationBarTitle(Text("List"))
}.onDelete(perform: xdelete)
}
}
}
func xdelete(at offsets: IndexSet) {
if let first = offsets.first {
print("remove \(first)")
oListDatasource.ListOfListEntries.remove(at: first)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Alle Apps ändern ihren Status. Zum Beispiel könnte der Benutzer auf eine Schaltfläche getippt haben, um weitere Informationen anzuzeigen, er könnte einen Text in ein Textfeld eingegeben oder ein Datum aus einer Datumsauswahl gewählt haben – alles Dinge, bei denen die App von einem Zustand in einen anderen wechselt.
Das Problem mit dem Zustand ist, dass er unübersichtlich ist: Wenn er sich ändert, müssen wir diese Änderung erkennen und unsere Layouts entsprechend aktualisieren. Das klingt zunächst vielleicht einfach, aber wenn unser Zustand wächst und wächst, wird es immer schwieriger – man vergisst leicht, eine Sache zu aktualisieren oder die Reihenfolge der Aktualisierung zu verwechseln, so dass der Zustand der Benutzeroberfläche nicht mit dem übereinstimmt, was erwartet wurde.
SwiftUI löst dieses Problem, indem es den Zustand aus unserer Kontrolle entfernt. Wenn wir Eigenschaften zu unseren Ansichten hinzufügen, sind sie effektiv inaktiv – sie haben zwar Werte, aber ihre Änderung bewirkt nichts. Wenn wir jedoch das spezielle @State-Attribut vor ihnen hinzugefügt haben, wird SwiftUI automatisch auf Änderungen achten und alle Teile unserer Ansichten, die diesen Zustand verwenden, aktualisieren.
Wenn es darum geht, sich auf einen Zustand zu beziehen – zum Beispiel, eine Zustands-Eigenschaft anzuweisen, sich zu ändern, wenn sich ein Kippschalter ändert – können wir nicht direkt auf die Eigenschaft verweisen. Das liegt daran, dass Swift denken würde, dass wir uns gerade auf den Wert beziehen, anstatt zu sagen: „Bitte passen Sie auf das Ding auf“. Glücklicherweise besteht die Lösung von SwiftUI darin, ein Dollarzeichen vor den Namen des Grundstücks zu setzen, wodurch wir uns auf die Daten selbst und nicht auf ihren aktuellen Wert beziehen können. Ich weiß, dass dies am Anfang etwas verwirrend ist, aber nach ein oder zwei Stunden wird es zur zweiten Natur.
Denken Sie daran, dass SwiftUI deklarativ ist, d.h. wir teilen ihm alle Layouts für alle möglichen Zustände im Voraus mit und lassen es herausfinden, wie es sich zwischen ihnen bewegen kann, wenn sich die Eigenschaften ändern. Wir nennen dies Bindung – wir bitten SwiftUI, Änderungen zwischen einem UI-Steuerelement und einer zugrunde liegenden Eigenschaft zu synchronisieren.
Die Arbeit mit State wird Ihnen anfangs einige Kopfschmerzen bereiten, wenn Sie an einen imperativeren Programmierstil gewöhnt sind, aber vertrauen Sie mir – wenn Sie damit fertig sind, ist die Sache klar. Übersetzt mit www.DeepL.com/Translator (kostenlose Version)
Egal ob Sie als Solo-Entwickler oder im Team arbeiten, wenn Sie für Ihre Projekte keine Quellcodekontrolle verwenden, sollten Sie es tun. Die Versionsverwaltung ist erstaunlich, weil sie Ihnen hilft, leichter zu älteren Versionen Ihres Codes zurückzukehren, neue Funktionen ohne Risiko zu Ihrer funktionierenden Anwendung hinzuzufügen, zu sehen, wie sich Ihr Code im Laufe der Zeit verändert hat, und als Team zu arbeiten. Und eines der besten Quellcode-Kontrollsysteme ist direkt in Xcode integriert – Git!
Git ist ein verteiltes Versionskontrollsystem, das ursprünglich von Linus Torvalds entwickelt wurde, dem Hauptverantwortlichen für die Entwicklung des Linux-Kernels. Das Schöne an Git ist, dass es kein zentrales Repository geben muss – jeder kann seine eigene Sicht auf den Code haben und Änderungen aus anderen Quellen einziehen.
In diesem Tutorial werden Sie praktische Erfahrungen mit Git sammeln und lernen, wie Sie es direkt in Xcode verwenden können.
Erste Schritte Anstatt über die Theorie des Git zu schwafeln, tauchen Sie gleich ein und probieren es aus. Sie werden ein neues Xcode-Projekt erstellen und einige Aufgaben ausprobieren, die Sie normalerweise täglich mit der Git-Quellcode-Kontrolle durchführen werden.
Starten Sie Xcode und erstellen Sie ein neues Single View Application-Projekt. Wählen Sie einen Speicherort und stellen Sie sicher, dass die Option Git-Repository auf meinem Mac erstellen ausgewählt ist, bevor Sie fortfahren. Sobald Sie dies getan haben, klicken Sie auf Erstellen.
Xcode wird Ihr neues Projekt zusammen mit einem neuen Git-Repository erstellen.
Alle Versionskontrollsysteme, einschließlich Git, speichern ihre Daten in einem Repository, damit sie Ihre Projektversionen verwalten und Änderungen während des gesamten Entwicklungszyklus verfolgen können. Stellen Sie sich ein Repository als eine Datenbank für Versionen vor.
Versions-Datenbank
Im Laufe der Arbeit an Ihrem Projekt werden Sie Dateien hinzufügen, Code modifizieren und Ihr Projekt viele Male ändern.
Nachdem Sie eine große Anzahl von Änderungen vorgenommen haben und sich Ihr Projekt in einem „bekannt guten“ Zustand befindet (normalerweise ein oder mehrere Male pro Tag), ist es eine gute Idee, Ihre Änderungen in das Repository einzuchecken. Dadurch erhalten Sie eine Aufzeichnung der „bekannt guten“ Zustände, zu denen Sie jederzeit zurückkehren können.
Aber was ist mit dem Code, der von der Projektvorlage erstellt wurde?
Ihr Projekt enthält nach wie vor nur die Vorlagendateien. Sie müssen noch nichts übergeben, weil Xcode dies für Sie getan hat, als Sie Ihr Projekt erstellt haben.
Um dies zu überprüfen, öffnen Sie den Navigator der Versionsverwaltung (Befehlstaste-2 ist die Tastenkombination). Stellen Sie nun sicher, dass der Versionsverwaltungsinspektor (Befehl-Option-3) ebenfalls geöffnet ist. Klicken Sie mit der Option auf das Offenlegungsdreieck neben GitUseExample im linken Fensterbereich, um alle in Ihrem Repository konfigurierten Zweige, Tags und Fernbedienungen anzuzeigen. Klicken Sie auf den Master-Zweig und dann auf die Erstübergabe im Editor-Fenster und Sie sehen die Details der automatischen Übertragung von Xcode.
Nehmen Sie jetzt einige Änderungen an Ihrem Projekt vor. Geänderte Dateien werden mit einem „M“ gekennzeichnet. Klicken sie mit der rechten Maustaste auf die Datei und wählen Commit. Nun befindet sich die Änderung im Repository und kann in dem Zustand jederzeit wiederhergestellt werden.
This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.