简体   繁体   English

在 Swift 中初始化期间为枚举大小写赋值

[英]Assign a value to an enum case during initalization in Swift

I'm decoding a JSON API to a struct, with a CodingKey enum in order to map the language key from the response to the name property of the struct:我正在使用CodingKey枚举将 JSON API 解码为结构,以便将语言键从响应映射到结构的name属性:

{
  id: "1",
  english: "United States",
  french: "États Unis",
  spanish: "Estados Unidos"
}
struct Country: Codable, Hashable, Identifiable {
  let id: String
  let name: String
  
  enum CodingKeys : String, CodingKey {
    case id
    case name = "french" 
  }
}

I want to be able to control programmatically the assigned name value in the CodingKeys enum so it'll be based on the user device locale.我希望能够以编程方式控制CodingKeys枚举中分配的name值,因此它将基于用户设备区域设置。

// English user
country.name // "United States"

// French user
country.name // "États Unis"

I have the function getUserLocale() that checks for the user's locale and returns the string value of it ( english , french , etc...).我有函数getUserLocale()来检查用户的语言环境并返回它的字符串值( englishfrench等...)。
How can I make it run during the enum initalization so it'll assign the locale value to the name property?如何让它在枚举初始化期间运行,以便将语言环境值分配给name属性?

Implementing custom decoding should work.实现自定义解码应该有效。 Here's an example.这是一个例子。

let sampleJSON = """
{
  "id": "1",
  "english": "United States",
  "french": "États Unis",
  "spanish": "Estados Unidos"
}
"""

var userLocale = "english"

struct Country: Decodable, Hashable, Identifiable {
    let id: String
    let name: String

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decode(String.self, forKey: .id)
        name = try values.decode(String.self, forKey: CodingKeys(rawValue: userLocale)!)
    }

    enum CodingKeys : String, CodingKey {
        case id
        case english
        case french
        case spanish
    }
}

let decoder = JSONDecoder()
let country = try decoder.decode(Country.self, from: sampleJSON.data(using: .utf8)!)

debugPrint(country)


userLocale = "french"
let anotherCountry = try decoder.decode(Country.self, from: sampleJSON.data(using: .utf8)!)
debugPrint(anotherCountry)

Regardless of the current language you have to decode the entire JSON anyway.无论当前使用何种语言,您都必须解码整个 JSON。

My suggestion is to add a function to return the localized name.我的建议是添加一个函数来返回本地化名称。

First create another enum for the supported languages首先为支持的语言创建另一个枚举

enum CountryCode : String {
    case en, fr, es
}

struct Country: Codable, Hashable, Identifiable {
  let id: String
  let english, french, spanish : String

  func name(for countryCode: CountryCode) -> String {
      switch countryCode {
          case .en: return english
          case .fr: return french
          case .es: return spanish
      }
  }
}

CountryCode is declared with a raw value to be able to initialize a value from the 2-letter country code. CountryCode使用原始值声明,以便能够从 2 个字母的国家/地区代码初始化值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM