Autor-Archiv Tobias Stephan

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 Conversion

These string operations in Swift can drive you crazy if you are used to a simple one from C#. So, I’ve been looking into it and I’ve put together a little bit here. I tested it with Swift 5.1

  • startIndex is the index of the first character
  • endIndex is the index after the last character
 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..



before refers to the index of the character directly before the specified index.

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

// range
let range = str.startIndex..



The OffsetBy value may be positive or negative and starts from the specified index. Although it is of type String.IndexDistance, you can pass an Int value.

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

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



The limitedBy is useful to ensure that the offset does not cause the index to exceed the limits. It is a limit index. Since it is possible for the offset to exceed the limit, this method returns an optional. It returns zero if the index is outside the limits.

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

If the offset had been 77 instead of 7, the if statement would have been skipped.

It would be much easier to use an Int index for strings. The reason you need to create a new String.index for each string is because the characters in Swift are not all the same length under the hood. A single Swift character can consist of one, two or even more Unicode code points. Therefore, each unique string must calculate the indices of its characters.

It is possible to hide this complexity behind an Int index extension, but I hesitate to do so. It's good to be reminded of what actually happens.

Translated with www.DeepL.com/Translator (free version)

The following Extenson must be added under your class in the code. This extension offers you the possibility to determine the index of a whole string within a string. In my example "ground".

String operations are thus addressed via indices and ranges. The index is therefore not a simple integer variable.

extension StringProtocol {
    func index(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.lowerBound
    }
    func endIndex(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.upperBound
    }
    func indices(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(of string: S, options: String.CompareOptions = []) -> [Range] {
        var result: [Range] = []
        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 Substring to String Conversion

Deze snaaroperaties in Swift kunnen je gek maken, zelfs als je gewend bent aan een eenvoudige van C#. Daarom heb ik er naar gekeken en een beetje van dit alles in elkaar gezet. Dit werd getest met Swift 5.1

  • startIndex is de index van het eerste teken
  • endIndex is de index na het laatste teken
    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..



verwijst naar de index van het teken direct voor de gespecificeerde index.

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

// range
let range = str.startIndex..



De OffsetBy waarde kan positief of negatief zijn en begint met de gespecificeerde index. Hoewel het van het type String.IndexDistance is, kunt u een Int-waarde doorgeven.

De limitedBy is nuttig om ervoor te zorgen dat de offset niet leidt tot overschrijding van de limieten van de index. Het is een limietindex. Aangezien het mogelijk is dat de offset de grenswaarde overschrijdt, geeft deze methode een optioneel karakter. Het geeft nul terug als de index buiten de limieten valt.

Als de verrekening 77 in plaats van 7 zou zijn geweest, dan zou de if-afrekening zijn overgeslagen.

Wat is het probleem?

Het zou veel gemakkelijker zijn om een Int-index voor snaren te gebruiken. De reden dat je voor elke string een nieuwe String.index moet maken is omdat de karakters in Swift niet allemaal even lang zijn onder de motorkap. Een enkel Swift-karakter kan bestaan uit één, twee of zelfs meer Unicode-codepunten. Daarom moet elke unieke string de indexen van zijn karakters berekenen.

Het is mogelijk om deze complexiteit te verbergen achter een Int-index extensie, maar ik aarzel om dat te doen. Het is goed om herinnerd te worden aan wat er werkelijk gebeurt.

Een nuttige Extension

De volgende Extenson moet worden toegevoegd onder uw klasse in de code. Deze uitbreiding biedt u de mogelijkheid om de index van een hele string binnen een string te bepalen. In mijn voorbeeld "grond".

String operaties worden dus aangepakt via indices en ranges. De index is dus geen eenvoudige gehele variabele.

Dieser Block enthält unerwarteten oder ungültigen Inhalt.LösenZu HTML umwandeln

extension StringProtocol {
    func index(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.lowerBound
    }
    func endIndex(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.upperBound
    }
    func indices(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(of string: S, options: String.CompareOptions = []) -> [Range] {
        var result: [Range] = []
        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 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..



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..



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..



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(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.lowerBound
    }
    func endIndex(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.upperBound
    }
    func indices(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(of string: S, options: String.CompareOptions = []) -> [Range] {
        var result: [Range] = []
        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

How to change Shopware demo logo

Settings > Theme Manager – Select Theme, then configure theme

The logo has the format 867px * 189px for the desktop version. For other devices the logo can be adapted accordingly. It can be easily exchanged via the above mentioned path.

VonTobias Stephan

Hide Shopware articles without stock

If you do not want articles without stock to be visible in the shop, you can do this by a simple setting in the basic settings menu in the Storefront category.

Basic settings >Storefront >Shopping cart/Article details > Deactivate sales articles without stock: Set to yes!

The sales setting for the respective article can be adjusted here:
Article > Overview > Edit article > Master data

VonTobias Stephan

Shopware Service Hotline how to change

The service hotline information is a text module. Text modules can be changed easily via „Settings – Text modules“.
So that you don’t have to search for the right text module forever, it is recommended to simply enter the word „Hotline“ in the search field.

VonTobias Stephan

Google Conversion ID Shopware – where can I find it?

In order to use Google Analytics and Adwords sensibly, you need the Conversion ID. This is stored in the Shopware Google Plugin.

The Conversion ID can be obtained via Adwords. There via Settings (click on the wrench) > Measurements > Conversions

The conversion ID in this example is: AW-961433594
The Conversion ID is then entered here. In case of several subshops, the conversion ID can of course differ and be generated for each individual shop.