Autor-Archiv Tobias Stephan

VonTobias Stephan

swift user defaults read set lesen schreiben

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:

Defaults deklarieren:

let defaults = UserDefaults.standard

Speichern eines Werts:

defaults.set(self.txtBenutzername.text , forKey: "UsernameKey")

Lesen eines Werts:

  if (defaults.string(forKey: "UsernameKey") != nil) {
            self.txtBenutzername.text = defaults.string(forKey: "UsernameKey")
}        
VonTobias Stephan

swiftui list array example load from xml feed

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.
//
//  XMLParser.swift
//  Listory
//
//  Created by T. Stephan on 15.02.20.
//  Copyright © 2020 eCommerce - Tobias Stephan. All rights reserved.
//
import UIKit
import Foundation
class ListoryXMLParser: UIViewController, XMLParserDelegate {
    var parser = XMLParser()

       let recordKey = "export"
       var dictionaryKeys = [String]() //"ASIN","Titel","Hersteller","Marke","BuyBoxPreis","Logdatum","Gesamtangebote","Bulletpoints"]

       // a few variables to hold the results as we parse the XML

       public var results: [[String: String]]? = [[String: String]]()         // the whole array of dictionaries
       var currentDictionary: [String: String]!                        // the current dictionary
       var currentValue: String?

       let defaults = UserDefaults.standard

       func beginParsing(tablename: String,criterion: String){
           let sASIN = ""
           beginParsing(tablename: tablename, criterion: criterion, asin: sASIN)
       }

       func beginParsing(tablename: String,criterion: String,asin: String)
       {
           results?.removeAll()
           //posts = []
           //let defaults = UserDefaults.standard

           var sHostname = "https://www.hostname.de/"

           if (defaults.string(forKey: "httpHostname") != nil){
               sHostname = defaults.string(forKey: "httpHostname")!
           }


           var sUrl = sHostname + "/exportxml.aspx?table=" + tablename + "&criterion=" + criterion



           if asin != "" {
               sUrl = sUrl + "&asin=" + asin
           }

           if (defaults.string(forKey: "fcm") != nil){
               sUrl = sUrl + "&token=" + defaults.string(forKey: "fcm")!
           }



           parser = XMLParser(contentsOf:(NSURL(string: sUrl))! as URL)!


           parser.delegate = self
           parser.parse()

       }


       func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {

           if elementName == recordKey {

               currentDictionary = [String : String]()

           } else if dictionaryKeys.contains(elementName) {

               currentValue = String()

           }
       }



       func parser(_ parser: XMLParser, foundCharacters string: String) {

           currentValue? += string

       }


       func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {

           if elementName == recordKey {

               results?.append(currentDictionary)
               currentDictionary = nil

           } else if dictionaryKeys.contains(elementName) {

               currentDictionary[elementName] = currentValue
               currentValue = nil

           }
       }

       func parserDidStartDocument(_ parser: XMLParser) {
           //results = [[:]]
       }

       func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {

           print(parseError)

       }
}

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()
    }
}
VonTobias Stephan

Swift UI arbeiten mit @State

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)

VonTobias Stephan

XCode Git Wiederherstellung Repository

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.

XCode Git Repository wiederherstellen

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.

VonTobias Stephan

Pour des raisons que je ne peux pas expliquer, la toile (de Canvas) n’était tout simplement plus affichée dans un fichier SwiftUI. La recherche sur Google n’a pas aidé non plus. J’utilise Catalina 10.15. Après tout, ça marchait avant. Dans le même projet avec d’autres fichiers SwiftUI, l’aperçu a également été affiché. Je recommande donc une solution de contournement rapide. Copier + Coller est la solution ici. Il suffit de créer un nouveau fichier et de supprimer l’ancien. Insérez à nouveau le code source et pouf… la prévisualisation est de retour. Bien sûr, vous devez vérifier si la toile est montrée.

Avec le menu Éditeur + Toile, la toile peut être affichée ou masquée. Une autre possibilité est la
Combinaison de touches : ALT – Commandement – RETURN

Ici dans l’image, vous pouvez cliquer sur le symbole en haut à droite, 2ème en partant de la droite.

VonTobias Stephan

swift canvas window not showing

For reasons I can’t explain, the canvas (from Canvas) was simply no longer displayed in a SwiftUI file. Googling did not help either. I use Catalina 10.15. After all it worked before. In the same project with other SwiftUI files the preview was also displayed. So I recommend a quick workaround. Copy + Paste is the solution here. Just create a new file and delete the old one. Insert the source code again and poof…the preview is back. Of course you should check if the canvas is shown at all.

With the menu Editor + Canvas the canvas can be shown or hidden. Another possibility is the
Key combination: ALT – Command – RETURN

Here in the picture you can click on the symbol on the top right, 2. from the right.

VonTobias Stephan

Xcode Swift UI Canvas Leinwand wird nicht angezeigt

Aus mir nicht erfindlichen Gründen wurde bei einem SwiftUI File einfach die Leinwand (von Canvas) nicht mehr angezeigt. Googeln half auch nicht. Catalina 10.15 setze ich ein. Schließlich hat es ja auch vorher funktioniert. Im gleichen Projekt mit anderen SwiftUI Files wurde die Preview auch angezeigt. Also empfehle ich einen flotten Workaround. Copy + Paste ist hier die Lösung. Einfach ein neues File anlegen und das alte Löschen. Quellcode wieder einfügen und schwups…die Preview ist wieder da. Natürlich sollte man vorher prüfen, ob die Leinwand überhaupt eingeblendet wird.

Über das Menü Editor + Canvas kann die Leinwand ein- bzw. ausgeblendet werden. Eine weitere Möglichkeit ist die
Tastenkombination: ALT – Command – RETURN

Hier im Bild kann man auf das Symbol rechts oben, 2. von rechts bemühen.

VonTobias Stephan

DataSet Tabelle entfernen c#

Eine DataTable mit dem Namen ‚export‘ gehört bereits zu diesem DataSet.

Die Fehlermeldung kennen wir alle. Wenn man diesen Fehler vermeiden möchte, kann man das ganz einfach umsetzen. Mit den folgenden Zeilen fragt man, ob die Tabelle im DataSet existiert

  if (dtDataSet.Tables.IndexOf("export") > -1)
     RemoveTableFromDataSet(dtDataSet, "export");

Hier findest Du Methode um die Tabelle aus dem bereits existierenden DataSet zu entfernen.

public static void RemoveTableFromDataSet(DataSet oDataSet, string TableName)
{
  DataTableCollection tablesCol = oDataSet.Tables;
  if (tablesCol.Contains(TableName) tablesCol.CanRemove(tablesCol[TableName]))
                tablesCol.Remove(TableName);
}

VonTobias Stephan

Swift print variable in string

So gibt man einfach den Wert einer Variable in Swift innerhalb eines strings aus.

let str = "Einfach mal den Wert einer Variable ausgeben..."
print("\(str!)")
VonTobias Stephan

Mac Backslash Hotkey Tastenkombination

Hey, ganz einfach und wirklich gut zu merken.

SHIFT + ALT + 7