Kategorien-Archiv Xcode Swift DE

VonTobias Stephan

Searchbar mit 2D Array verbinden und ein TableView durchsuchen Swift 5.1

Hier findest Du die wesentlichen Dinge, die Du brauchst um ein TableView zu durchsuchen. Zuerst ziehst Du mal eine Searchbar aus dem Objektkatalog und erstellst im Code ein Outlet.

Nachdem Du das Outlet im Quelltext gesetzt hast, setze das delegate.

Jetzt benötigen wir noch eine Variable “searching” sowie ein weiteres 2-dimensionales Array. Die Variable searching bekommt den Wert true, während eine Suche stattfindet. Hier im Beispiel siehst du die Variable für das 2. Array, dass baugleich mit dem Array results ist. In das 2. Array wird jeweils das Filterergebnis gesetzt. Jetzt weißt Du, warum wir die Boolean Variable “searching” benötigen. So kann man für alle weiteren Aktionen im Code abfragen, aus welchem Array man sich gerne bedienen möchte. Je nachdem ob halt gerade gesucht wird oder die Komplette Liste im Tableview dargestellt wird.

var searching = false
var filteredresults: [[String: String]]? = [[String: String]]()
Nun diese extension hinzufügen. Hier wird das 2. Array filteredresults mit dem Filterergebnis gefüllt und festgelegt ob unsere Variable searching true oder false gesetzt wird. Logischerweise wird
seraching = false
gesetzt, wenn
filteredresults!.count == 0
Datensätze enthält.
extension ViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
       
        filteredresults = self.results!.filter ({
            
            $0["ASIN"]!.localizedCaseInsensitiveContains(searchText)

        })
        if(filteredresults!.count == 0){
            searching = false
        }else{
            searching = true
        }

        self.tableView.reloadData()

    }
}
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        if (searching){
            return filteredresults!.count
        }else {
            return (results!.count)
        }
    }

Beim füllen der Felder in der Tableview Cell darauf achten, daß auch hier aus dem richtigen Array abgegriffen wird.

if (searching){

            cell.lblASIN.text = filteredresults![indexPath.row]["ASIN"]
        }
        else
        {
            cell.lblASIN.text = results![indexPath.row]["ASIN"]
        }

Hier solltest Du natürlich auch darauf achten, dass numberOfRowsInSection jeh nach Suchzustand korrekt zurückgeliefert wird.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        if (searching){
            return filteredresults!.count
        }else {
            return (results!.count)
        }
    }

VonTobias Stephan

Wann wird meine App im Store von Apple angezeigt?

Ich berichte hier einfach mal aus Erfahrung. Die Theorie sagt, dass App’s im App Store von Apple nach 24 Stunden in der Suche aufgefunden werden. In der Praxis durchaus nach wenigen Minuten. Wir sprechen hier von App’s, die gerade das Approval erhalten haben und zum ersten mal im App-Store zur Verfügung stehen. Wenn Deine App gerade frisch das Approval erhalten hat, ist Sie nicht automatisch sofort auffindbar.

Apple Appstore Approval

Trotzdem darfst Du Dich freuen, wenn Du diese Mail bekommst. Das Approval kann doch manchmal ein nervender Prozess sein. Am Ende entscheiden Menschen und keine Algorithmen. Menschen sind in Ihren Entscheidungen nun einmal subjektiv. Sicherlich kann jeder App-Entwickler von seinen Erfahrungen berichten. Hier gilt aber, einfach nicht aufgeben. Eine App kann durchaus auch mal abgelehnt werden, obwohl Sie schon lange zugelassen wurde. Der nächste Mitarbeiter von Apple schaut vielleicht auch mal etwas genauer hin und hat etwas zu meckern. In den meisten Fällen haben Sie bei genauer Betrachtung recht – nur manchmal wird es etwas merkwürdig. Dann gilt stumpf…App an die Anforderungen anpassen.

VonTobias Stephan

Swift Datum formatieren

Hier jetzt mal in ganz einfach. In diesem Beispiel habe ich mit Swift 5.1 gearbeitet.

Wir möchten das Datum im Format:
2020-01-06T19:23:43.97+01:00 – ISO8601
in das Format:
06.01.2020 07:23:43
konvertieren.

   let dateFormatter = DateFormatter()
   //Wir erhalten das Ausgangsformat ISO8601
   //Beispiel: 2020-01-06T19:23:43.97+01:00
   dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
   //Das Datum wird aus einem XML Stream geladen
   let stringDate : String = oAMZXMLParser.results![0]["Logdatum"]!
   print(stringDate)
   //Aus dem String wird in das Date Format konvertiert
   let date = dateFormatter.date(from: stringDate)

   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: date!)
   print(sNewDateFormat)

Jetzt liegt es an Dir andere Formate zu wählen.

VonTobias Stephan

Swift Substring to String

Herrjeh…diese String-Operationen in Swift können einen schon wahnsinnig machen, wenn man aus C# ein einfaches gewohnt ist. Deshalb habe ich mich damit auseinander gesetzt und hier ein wenig zusammengetragen. Getestet wurde das mit Swift 5.1

  • startIndex ist der Index des ersten Zeichens
  • endIndex ist der Index nach dem letzten Zeichen
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        let str = "Hello, playground"
        print(str[str.startIndex]) // H
        //print(str[str.endIndex])   // error: after last character

        let rangeStartToEnd = str.startIndex..<str.endIndex
        print("Range: " + str[rangeStartToEnd])  // "Hello, playground"

        let rangeWithoutGround = str.startIndex..<str.index(of: "ground")!
        print("Range: " + str[rangeWithoutGround])  // "Hello, playground"
    }

before bezieht sich auf den Index des Zeichens direkt vor dem angegebenen Index.

// character
let index = str.index(before: str.endIndex)
str[index] 

// range
let range = str.startIndex..<str.index(before: str.endIndex)
str[range]

Der OffsetBy-Wert kann positiv oder negativ sein und beginnt ab dem angegebenen Index. Obwohl er vom Typ String.IndexDistance ist, können Sie einen Int Wert übergeben.

// character
let index = str.index(str.startIndex, offsetBy: 7)
str[index]

// range
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
str[range]

Das limitedBy ist nützlich, um sicherzustellen, dass der Offset nicht dazu führt, dass der Index über die Grenzen hinausgeht. Es ist ein Begrenzungsindex. Da es möglich ist, dass der Offset die Grenze überschreitet, gibt diese Methode ein Optional zurück. Sie gibt null zurück, wenn der Index außerhalb der Grenzen liegt.

if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) {
    str[index]
}

Wäre der Offset 77 statt 7 gewesen, dann wäre die if-Anweisung übersprungen worden.

Warum denn nun der ganze Umstand?

Es wäre viel einfacher, einen Int-Index für Strings zu verwenden. Der Grund dafür, dass Sie für jeden String einen neuen String.Index erstellen müssen, ist, dass die Zeichen in Swift nicht alle gleich lang unter der Haube sind. Ein einzelnes Swift-Zeichen kann aus einem, zwei oder sogar mehreren Unicode-Codepunkten bestehen. Daher muss jeder eindeutige String die Indizes seiner Zeichen berechnen.

Es ist möglich, diese Komplexität hinter einer Int-Indexerweiterung zu verbergen, aber ich zögere, dies zu tun. Es ist gut, an das erinnert zu werden, was tatsächlich passiert.

Übersetzt mit www.DeepL.com/Translator (kostenlose Version)

Eine hilfreiche Extension

Folgende Extenson muss noch unter Deine Klasse im Code gehängt werden. Diese Extension bietet Dir die Möglichkeit innerhalb eines String gleich den Index einer ganzen Zeichenfolge zu ermitteln. In meinem Beispiel “ground”.

String-Operationen werden also über Indices und Ranges angesprochen. Der Index ist also keine einfache Integervariable.

extension StringProtocol {
    func index<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.lowerBound
    }
    func endIndex<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.upperBound
    }
    func indices<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Index] {
        var indices: [Index] = []
        var startIndex = self.startIndex
        while startIndex < endIndex,
            let range = self[startIndex...]
                .range(of: string, options: options) {
                indices.append(range.lowerBound)
                startIndex = range.lowerBound < range.upperBound ? range.upperBound :
                    index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        }
        return indices
    }
    func ranges<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Range<Index>] {
        var result: [Range<Index>] = []
        var startIndex = self.startIndex
        while startIndex < endIndex,
            let range = self[startIndex...]
                .range(of: string, options: options) {
                result.append(range)
                startIndex = range.lowerBound < range.upperBound ? range.upperBound :
                    index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        }
        return result
    }
}
VonTobias Stephan

Swift String Zeichen abschneiden

So konvertiert man einen Substring in einen String
Swift: 5.1

Swift hat einen dedizierten Substring-Typ (String.SubSequence), der für die Aufnahme von Teilen eins Strings ausgelegt ist, was eine Leistungsoptimierung darstellt: Wenn Sie einen Teil eines Strings in einer anderen Variablen speichern, kann Swift den Substring einfach auf den übergeordneten String zeigen, anstatt alle Daten zu kopieren.

Obwohl Teilzeichenketten auf viele der gleichen Arten wie normale Zeichenketten verwendet werden können, sind sie nicht gleich – wenn Sie eine Funktion haben, die eine Zeichenkette als Parameter akzeptiert, können Sie ihr einfach keine Teilzeichenkette senden.

Um dies zu beheben, können Sie Ihren Substring in einen String-Initialisierer wie folgt einpacken:

let quote = "The revolution will be Swift"
let substring = quote.dropFirst(23)
let realString = String(substring)
VonTobias Stephan

Swift 5 Timer Event Beispiel Sample

Dieses Timer Event Beispiel kannst Du einfach in die viewDidLoad() Methode packen.

Im Ausgabe Fenster kannst du verfolgenden, wie das Ereignet alle 5 Sekunden “gefeuert” wird.

let timer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { timer in
print("Timer fired!")

}
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd hh:mm:ss"
let sDate = df.string(from: timer.fireDate)
print(sDate)

VonTobias Stephan

Navigation Controller Swift Back Button

Zu diesem Titel findet man zahlreiche Beiträge. In diesem Beispiel soll von dem Button “Geschwindigkeit lernen” der nächste ViewController aufgerufen werden. Der Zurück-Button ist hier total wichtig…denn sonst gibt es keinen Weg zurück

dasdf

Das Segue hab ich einfach mit Rechts-Click auf den Button erstellt.

 

 

 

 

VonTobias Stephan

Swift 5.1 JSON to Object auslesen

Hier ein einfaches Beispiel, wie man ein Json String auslesen bzw. parsen kann.

let str = "{\"names\": [\"Bob\", \"Tim\", \"Tina\"]}"
let data = Data(str.utf8)

do {
    // Sicher stellen, dass es sich um das korrekte JSON Format handelt
    if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
        // try to read out a string array
        if let names = json["names"] as? [String] {
            print(names)
        }
        for (key, value) in json {
            print("\(key) : \(value)")
        }
    }
} catch let error as NSError {
    print("Failed to load: \(error.localizedDescription)")
}

VonTobias Stephan

Swift 5 App im Hintergrund erkennen (app moved to background)

Mit diesen Codzeilen kann man erkennen, ob eine App in den Hintergund geschoben wird.

 override func viewDidLoad() {
        super.viewDidLoad()

        let notificationCenter = NotificationCenter.default
        notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)

    }

    @objc func appMovedToBackground() {
        print ("App moved to Background")
    }

VonTobias Stephan

Swift 5 App im Vorderung erkennen (app moved to foreground)

Manchmal ist es sinnvoll zu erkenne, ob die eigene App in den Vordergrund geschoben wird. Mit diesen paar Codezeilen ist das leicht zu ermitteln.

   override func viewDidLoad() {
        super.viewDidLoad()
        

       

        let notificationCenter = NotificationCenter.default
        notificationCenter.addObserver(self, selector: #selector(appMovedToForeground), name: UIApplication.willEnterForegroundNotification, object: nil)

    }

    @objc func appMovedToForeground() {
        //do stuff
    }