Author Archive Tobias Stephan

ByTobias 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..<str.endIndex
        print("Range: " + str [rangeStartToEnd]) // "Hello, playground"

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

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..<str.index(before: str.endIndex)
str[range] // Hello, playgroun

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..<end
str[range] // play

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

ByTobias 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

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

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

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

ByTobias Stephan

Shopware API article is not displayed

If the article is not displayed in the storefront, this can have various reasons. Over time, you will develop a feeling for the “shopware needs”.  First of all, you need to check if the item is assigned to an active category. If this is not the case, the item cannot be displayed. If you create the articles via the API, the article must be set to active = true in the article object as well as in the article details object.

ByTobias Stephan

shopware insert platform logo

If you simply insert the link, Shopware will automatically give the link a NOFOLLOW attribute. Idealo has asked me to remove this, as this is understandably not in accordance with the agreement. Just add the link without http:// and it will work.

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

Integrate platform logo into shopware via the hotline text module
Integrate platform logo into shopware via the hotline text module
Shopware Idealo Logo Beispielintegration
Example of an logo integrated into a Shopware Shop

ByTobias Stephan

Reset iRobot 780 to factory settings 700 Series

Press and hold the Start button and hold the Dock and Spot buttons for 10 seconds. The display shows the message r5t – this means that the settings are now reset.