Swift3.0 Не удается преобразовать значение типа «ClosedRange‹Index›» в тип «Range‹Index›»

Я пытаюсь перенести Swift 2.3 на 3.0 и постконвертировать, сталкиваясь с этой проблемой. Любое предложение, что я делаю неправильно.

Свифт 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
    }

Ошибка:

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>')

Исходный код: 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
    }

person Anna23    schedule 17.08.2016    source источник


Ответы (2)


Вы можете использовать ..< вместо ..., чтобы range имел тип Range<Index> вместо ClosedRange<Index>, и в этом случае вызов stringByReplacingCharactersInRange(...) не приведет к ошибке (обратите внимание, что offsetBy увеличивается на 1).

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

Теперь я могу ошибаться, но кажется, что вы просто хотите, чтобы selectorString была версией key с первым символом в верхнем регистре. Альтернативный метод для вашего решения диапазона вы можете, например. используйте решение расширения String следующим образом:

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
person dfrib    schedule 17.08.2016

Свифт 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)
    }
person Dasoga    schedule 27.08.2017