This solution with two integers works, but I'd like to use a range instead:
extension String {
subscript(start: Int, end: Int) -> String? {
return String(self[index(startIndex, offsetBy: start#)...index(startIndex, offsetBy: end)])
}
}
The two following solutions use ranges, but both produce the same error, not in the extension code, but when attempting to use it:
'subscript' is unavailable: cannot subscript String with an integer range.
This is an absurd error that's basically telling me there is no range subscript for String, when in fact I just created it, so it DOES exist.
extension String {
subscript(range: Range<String.IndexDistance>) -> String? {
return String(self[index(startIndex, offsetBy: range𝜮.startIndex)...index(startIndex, offsetBy: range𝜮.endIndex)])
}
subscript(range: Range<Int>) -> String? {
return String(self[index(startIndex, offsetBy: range.startIndex)...index(startIndex, offsetBy: range.endIndex)])
}
}
let greeting = "Hello, World"
print(greeting[0...4]) // should print "Hello"
The compiler error is not unexpected. The type of the range 0...4
is not Range<Int>
, but ClosedRange<Int>
, which are unrelated types. If you modify your subscript
implementation to take a ClosedRange<Int>
instead of a Range<Int>
, your code compiles and works just fine.
extension String {
subscript(range: ClosedRange<Int>) -> String? {
return String(self[index(startIndex, offsetBy: range.lowerBound)...index(startIndex, offsetBy: range.upperBound)])
}
}
If you want to return nil
in case any of the indices would produce a range out of bounds exception, you can use index(_:,offsetBy:,limitedBy:)
.
extension String {
subscript(range: ClosedRange<Int>) -> String? {
guard let startIndex = index(startIndex, offsetBy: range.lowerBound,limitedBy: endIndex), let endIndex = index(startIndex, offsetBy: range.upperBound,limitedBy: endIndex) else { return nil }
return String(self[startIndex...endIndex])
}
}