Преобразование типа ключа словаря в Swift 5 с помощью словаря (uniqueKeysWithValues ​​:) - PullRequest
2 голосов
/ 13 апреля 2020

Я пишу приложение с сетевыми возможностями для iOS 13.4 (Swift 5, Xcode 11) с использованием Alamofire 5. Я создал свой пользовательский тип typealias KeyedParameters = [ParameterKeys: Any], чтобы иметь возможность быстро использовать мои ключи параметров API в «быстром» режиме. короткий путь (т. е. .login вместо KeyedParameters.login.rawValue).

Проблема в том, что когда я пытаюсь преобразовать этот тип обратно в стандартное значение Alamofire Parameters, я получаю следующую ошибку: Cannot convert return expression of type 'Dictionary<ParameterKeys, Any>' to return type 'Parameters' (aka 'Dictionary<String, Any>').

Casting:

extension KeyedParameters {
    var parameters: Parameters {
        Dictionary(uniqueKeysWithValues: map { ($0.key.rawValue, $0.value) })
    }
}

Ключи Parameter:

enum ParameterKeys: String {
    // MARK: - Auth and User
    case id, login, password, email, name
    case createdAt = "created_at"
    ...
}

Как выглядит ошибка:

enter image description here

Ответы [ 2 ]

3 голосов
/ 14 апреля 2020

Я думаю, что это может быть просто ошибочным сообщением об ошибке.

Ваше расширение KeyedParameters (typealias для [ParameterKeys: Any]) фактически эквивалентно:

extension Dictionary where Key == ParameterKeys, Value: Any { ...

Swift имеет странное поведение при вызове инициализатора для обобщенного типа c в объявлении самого этого типа. Если типы generi c различаются, это не будет обрабатываться должным образом.

Вот более простой пример без большого количества красных строк (псевдонимы типов, необработанные значения enum и т. Д. c.) И зависимостей:

extension Dictionary  {
    func returnADifferentDict() -> [Character: String] {
        let words = [
            "apple", "anchovies",
            "bacon", "beer",
            "celery"
        ]

        return Dictionary(uniqueKeysWithValues:
            words.map { ($0.first!, $0) }
        )

//      fixed:
//      return Dictionary<Character, String>(uniqueKeysWithValues:
//          words.map { ($0.first!, $0) }
//      )

    }
}

Решение состоит в том, чтобы явно указать параметры типа generi c для типа generi c, который вы инициализируете. В вашем случае

extension KeyedParameters {
    var parameters: Parameters {
        Dictionary<String, Any>(uniqueKeysWithValues: map { ($0.key.rawValue, $0.value) })
    }
}
2 голосов
/ 14 апреля 2020

Вы бы лучше явно выделить тип, например, так:

extension KeyedParameters {
    var parameters: Parameters {
        return Parameters(uniqueKeysWithValues:
            self.map { (key, value) in (key.rawValue, value) }
        )
    }
}

Сработало для меня.

...