使用 Dictionary(uniqueKeysWithValues:) 转换 Swift 5 中的字典键类型

Converting Dictionary Key type in Swift 5 with Dictionary(uniqueKeysWithValues:)

我正在使用 Alamofire 5 为 iOS 13.4(Swift 5,Xcode 11)编写具有网络功能的应用程序。我已经创建了自定义类型 typealias KeyedParameters = [ParameterKeys: Any]能够以 'swifty' 简短的方式使用我的 API 参数键(即 .login 而不是 KeyedParameters.login.rawValue)。

问题是当我尝试将此类型转换回默认的 Alamofire Parameters 时,我收到以下错误:Cannot convert return expression of type 'Dictionary<ParameterKeys, Any>' to return type 'Parameters' (aka 'Dictionary<String, Any>')

选角:

extension KeyedParameters {
    var parameters: Parameters {
        Dictionary(uniqueKeysWithValues: map { ([=11=].key.rawValue, [=11=].value) })
    }
}

参数键:

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

错误的外观:

你最好像这样明确地突出显示类型:

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

对我有用。

我认为这可能只是错误消息的一个例子。

您的扩展 KeyedParameters[ParameterKeys: Any]typealias)实际上等同于:

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

Swift 在该类型本身的声明中调用泛型类型的初始值设定项时有一些奇怪的行为。如果通用类型不同,它将无法正确处理。

这里有一个更简单的示例,没有太多无关紧要的内容(类型别名、枚举原始值等)和依赖项:

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

        return Dictionary(uniqueKeysWithValues:
            words.map { ([=11=].first!, [=11=]) }
        )

//      fixed:
//      return Dictionary<Character, String>(uniqueKeysWithValues:
//          words.map { ([=11=].first!, [=11=]) }
//      )

    }
}

解决方案是显式指定要初始化的泛型类型的泛型类型参数。在你的情况下,

extension KeyedParameters {
    var parameters: Parameters {
        Dictionary<String, Any>(uniqueKeysWithValues: map { ([=12=].key.rawValue, [=12=].value) })
    }
}