Autor-Archiv Tobias Stephan

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.

VonTobias Stephan

Shopware order status IDs from the table s_core_states

Leckerstecker.e Sample

To adjust the status of an order via the Shopware API, you need the respective status IDs. These can be found in the following table.

Status IDBeschreibung
-1Abgebrochen
0Offen
1In Bearbeitung (Wartet)
2Komplett abgeschlossen
3Teilweise abgeschlossen
4Storniert / Abgelehnt
5Zur Lieferung bereit
6Teilweise ausgeliefert
7Komplett ausgeliefert
8Klärung notwendig
VonTobias Stephan

Shopware according to EuGH judgement Cookies only with consent

Today, the European Court of Justice gave a fundamental answer to a legal question that has been smouldering for years: the question was whether the consent of site visitors is required for the lawful processing of cookies.

Shopware brings all the necessary things with it from home. Settings, basic settings, search for „privacy“

Of course the hint must be displayed first. Cookies are allowed to my knowledge, but only if they are technically necessary. Therefore I recommend the cookie hint mode „Technically necessary cookies allowed, ask for the rest“.

After saving the settings, do not forget to empty the shop cache. You can do this via the menu or with the key combination CTRL-ALT-X.