Reputation: 700
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.
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>')
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
}
Upvotes: 22
Views: 15359
Reputation: 5695
Swift 3+
override func setValue(_ value: Any?, forKey key: String) {
let upperCaseFirstCharacter = String(key.characters.first!).uppercased()
let range = key.startIndex..<key.index(key.startIndex, offsetBy: 1)
let selectorString = key.replacingCharacters(in: range, with: upperCaseFirstCharacter)
let selector = NSSelectorFromString("set\(selectorString):")
let responds = self.responds(to: selector)
if !responds{
return
}
super.setValue(value, forKey: key)
}
init(dictionary: [String: Any]){
super.init()
setValuesForKeys(dictionary)
}
Upvotes: 0
Reputation: 73236
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
Upvotes: 24