Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
    }
like image 832
Anna23 Avatar asked Aug 17 '16 08:08

Anna23


1 Answers

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
like image 102
dfrib Avatar answered Oct 23 '22 03:10

dfrib