Swift3.0 Cannot convert value of type 'ClosedRange<Index>' to type 'Range<Index>'

13,134

You can use ..< instead of ... for range to be of type Range<Index> instead of ClosedRange<Index>, in which case the call to stringByReplacingCharactersInRange(...) wont yield an error (notice the offsetBy increase by 1).

let range = key.startIndex..<key.index(key.startIndex, offsetBy: 1)
// range is now type Range<Index>

Now, I might be wrong, but it seems as if you simply want the selectorString to be the version of key with the first character uppercased. An alternative method to your range solution you can e.g. use a String extension solution as follows:

extension String { 
   var firstCharacterUppercased: String {
        guard case let c = self.characters,
                   let c1 = c.first else { return self }
        return String(c1).uppercased() + String(c.dropFirst())
    }
}

/* example usage */
let key = "fooBar"
let selectorString = key.firstCharacterUppercased

print(selectorString) // FooBar
Share:
13,134

Related videos on Youtube

Anna23
Author by

Anna23

Software Engineer

Updated on June 15, 2022

Comments

  • Anna23
    Anna23 almost 2 years

    I'm trying to migrate the Swift 2.3 to 3.0 and post-conversion facing this issue. Any suggestion what I'm doing wrong.

    Swift 3.0:

    override func setValue(_ value: AnyObject?, forKey key: String) {
        let uppercasedFirstCharacter = String(key.characters.first!).uppercased()
        let range = key.startIndex...key.index(key.startIndex, offsetBy: 0)
        let selectorString = key.replacingCharacters(in: range, with: uppercasedFirstCharacter)
    
        let selector = NSSelectorFromString("set\(selectorString):")
        let responds = self.responds(to: selector)
    
        if !responds {
            return
        }
    

    Error:

    let selectorString = key.replacingCharacters(in: range, with: uppercasedFirstCharacter)

    Cannot convert value of type 'ClosedRange<Index>' (aka 'ClosedRange<String.CharacterView.Index>') to expected argument type 'Range<Index>' (aka 'Range<String.CharacterView.Index>')
    

    Original code: Swift 2.3

    override func setValue(value: AnyObject?, forKey key: String) {
        let uppercasedFirstCharacter = String(key.characters.first!).uppercaseString
    
        let range = key.startIndex...key.startIndex.advancedBy(0)
        let selectorString = key.stringByReplacingCharactersInRange(range, withString: uppercasedFirstCharacter)
    
        let selector = NSSelectorFromString("set\(selectorString):")
        let responds = self.respondsToSelector(selector)
    
        if !responds {
            return
        }