'subscript' is unavailable: cannot subscript String with a CountableClosedRange<Int>, see the documentation comment for discussion
- If you want to use subscripts on Strings like
"palindrome"[1..<3]
and"palindrome"[1...3]
, use these extensions.
Swift 4
extension String {
subscript (bounds: CountableClosedRange<Int>) -> String {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return String(self[start...end])
}
subscript (bounds: CountableRange<Int>) -> String {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return String(self[start..<end])
}
}
Swift 3
For Swift 3 replace with return self[start...end]
and return self[start..<end]
.
- Apple didn't build this into the Swift language because the definition of a 'character' depends on how the String is encoded. A character can be 8 to 64 bits, and the default is usually UTF-16. You can specify other String encodings in
String.Index
.
This is the documentation that Xcode error refers to.
More on String encodings like UTF-8 and UTF-16
Your question (and self-answer) has 2 problems:
Subscripting a string with Int
has never been available in Swift's Standard Library. This code has been invalid for as long as Swift exists:
let mySubstring: Substring = myString[1..<3]
The new String.Index(encodedOffset: )
returns an index in UTF-16 (16-bit) encoding. Swift's string uses Extended Grapheme Cluster, which can take between 8 and 64 bits to store a character. Emojis make for very good demonstration:
let myString = ""
let lowerBound = String.Index(encodedOffset: 1)
let upperBound = String.Index(encodedOffset: 3)
let mySubstring = myString[lowerBound..<upperBound]
// Expected: Canadian and UK flags
// Actual : gibberish
print(mySubstring)
In fact, getting the String.Index
has not changed at all in Swift 4, for better or worse:
let myString = ""
let lowerBound = myString.index(myString.startIndex, offsetBy: 1)
let upperBound = myString.index(myString.startIndex, offsetBy: 3)
let mySubstring = myString[lowerBound..<upperBound]
print(mySubstring)
- How can I resolve this error?
This error means you can't use an Int in the subscript format – you have to use a String.Index, which you can initialize with an encodedOffset Int.
let myString: String = "foobar"
let lowerBound = String.Index.init(encodedOffset: 1)
let upperBound = String.Index.init(encodedOffset: 3)
let mySubstring: Substring = myString[lowerBound..<upperBound]
- Where is "the documentation comment for discussion" that was referred to in the error?
It's on GitHub in the Swift Standard Library repository in a file called UnavailableStringAPIs.swift.gyb in the bottom of a locked filing cabinet stuck in a disused lavatory with a sign on the door saying 'Beware of the Leopard'. link