'subscript' is unavailable: cannot subscript String with a CountableClosedRange, see the documentation comment for discussion

前端 未结 8 829
谎友^
谎友^ 2021-01-31 13:57

In Swift 4, I\'m getting this error when I try to take a Substring of a String using subscript syntax.

\'subscript\' is unavaila

相关标签:
8条回答
  • 2021-01-31 14:35
    1. 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].

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

    0 讨论(0)
  • 2021-01-31 14:36

    Building on both p-sun's and Justin Oroz's answers, here are two extensions that protect against invalid indexes beyond the start and end of a string (these extensions also avoid rescanning the string from the beginning just to find the index at the end of the range):

    extension String {
    
        subscript(bounds: CountableClosedRange<Int>) -> String {
            let lowerBound = max(0, bounds.lowerBound)
            guard lowerBound < self.count else { return "" }
    
            let upperBound = min(bounds.upperBound, self.count-1)
            guard upperBound >= 0 else { return "" }
    
            let i = index(startIndex, offsetBy: lowerBound)
            let j = index(i, offsetBy: upperBound-lowerBound)
    
            return String(self[i...j])
        }
    
        subscript(bounds: CountableRange<Int>) -> String {
            let lowerBound = max(0, bounds.lowerBound)
            guard lowerBound < self.count else { return "" }
    
            let upperBound = min(bounds.upperBound, self.count)
            guard upperBound >= 0 else { return "" }
    
            let i = index(startIndex, offsetBy: lowerBound)
            let j = index(i, offsetBy: upperBound-lowerBound)
    
            return String(self[i..<j])
        }
    }
    
    0 讨论(0)
  • 2021-01-31 14:36
    extension String {
    
        subscript(bounds: CountableClosedRange<Int>) -> String {
            let lowerBound = max(0, bounds.lowerBound)
            guard lowerBound < self.count else { return "" }
    
            let upperBound = min(bounds.upperBound, self.count-1)
            guard upperBound >= 0 else { return "" }
    
            let i = index(startIndex, offsetBy: lowerBound)
            let j = index(i, offsetBy: upperBound-lowerBound)
    
            return String(self[i...j])
        }
    
        subscript(bounds: CountableRange<Int>) -> String {
            let lowerBound = max(0, bounds.lowerBound)
            guard lowerBound < self.count else { return "" }
    
            ***let upperBound = min(bounds.upperBound, self.count-1)***
            guard upperBound >= 0 else { return "" }
    
            let i = index(startIndex, offsetBy: lowerBound)
            let j = index(i, offsetBy: upperBound-lowerBound)
    
            return String(self[i..<j])
        }
    }
    
    0 讨论(0)
  • 2021-01-31 14:36

    You getting this error because result of subscript with range is Substring? not Substring.

    You must use following code:

    let myString: String = "foobar"
    let mySubstring: Substring? = myString[1..<3]
    
    0 讨论(0)
  • 2021-01-31 14:38
    1. 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]
    
    1. 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

    0 讨论(0)
  • 2021-01-31 14:40

    You could just convert your string to an array of characters...

    let aryChar = Array(myString)
    

    Then you get all the array functionality...

    0 讨论(0)
提交回复
热议问题