Why does String.subscript(_:) require the types `S

2020-04-14 12:18发布

问题:

I fail to understand the problem Xcode is confronting me with in this line:

iteration.template = template[iterationSubstring.endIndex...substring.startIndex]

template is a String and iterationSubstring and substring are Substrings of template. Xcode highlights the opening square bracket with the following message:

Subscript 'subscript(_:)' requires the types 'Substring.Index' and 'Int' be equivalent

The error message does not make any sense to me. I try to obtain a Substring by creating a Range<String.Index> with the [template.startIndex...template.endIndex] subscript. How is this related to Int? And why does the same pattern work elsewhere?


Xcode playground code reproducing the problem:

import Foundation
let template = "This is an ordinary string literal."

let firstSubstringStart = template.index(template.startIndex, offsetBy: 5)
let firstSubstringEnd = template.index(template.startIndex, offsetBy: 7)
let firstSubstring = template[firstSubstringStart...firstSubstringEnd]

let secondSubstringStart = template.index(template.startIndex, offsetBy: 10)
let secondSubstringEnd = template.index(template.startIndex, offsetBy: 12)
let secondSubstring = template[secondSubstringStart...secondSubstringEnd]

let part: String = template[firstSubstring.endIndex...secondSubstring.startIndex]

After all I have a template string and two substrings of it. I want to get a String ranging from the end of the first Substring to the start of the second Substring.

回答1:

The current version of Swift works with the Substring struct which is a sliced String.

The error seems to be misleading and occurs if you are going to assign a (range-subscripted) Substring to a String variable.

To fix the error create a String from the Substring

iteration.template = String(template[iterationSubstring.endIndex...substring.startIndex])

Nevertheless you are strongly discouraged from creating ranges with indices from different strings (iterationSubstring and substring). Slice the main string, the indices are preserved.


The crash in the second (meanwhile deleted) example occurred because the last character of a string is at index before endIndex, it's

template[template.startIndex..<template.endIndex] 

or shorter

template[template.startIndex...]