【问题标题】:Sub enumeration rawValue子枚举 rawValue
【发布时间】:2019-06-17 22:46:59
【问题描述】:

考虑下面的代码,我在其中声明了一个enum,其中包含子枚举。

enum LocalizeKey {
case message(Messages)
case buttons(Buttons)
enum Buttons: String {
    case remove = "Remove"
    case add = "Add"
}
enum Messages: String {
    case success = "Success"
    case failure = "Failure"
 }
}

在没有子枚举的普通enum 中,我们可以轻松访问.rawValue 属性并获取我们选择的任何情况的原始值。

对于这种情况,我创建了一个这样的函数只是为了检查我得到了什么。

func keyString(for type: LocalizeKey) {
    print(type)
 }
keyString(for: .message(.failure)) // usage

问题:除了.self 之外,没有其他属性可以访问此LocalizeKey 枚举。

我想要实现的目标:也许你可以通过命名来联系,我正在尝试包装我的本地化密钥,所以我可以根据密钥类型等轻松访问它们,以及 @引用实际密钥的 987654328@ 将进入 getLocalizedValue 函数。

Playground 输出:使用上面的函数 Playground 输出是

消息(__lldb_expr_21.LocalizeKey.Messages.failure)

编辑:无需创建一个在每种情况下都切换 self 的变量,想象一下如果我们有 +400 键,那可能会是一团糟。

【问题讨论】:

  • 如果我理解正确,您希望能够在keyString 函数中访问ButtonsMessages 的原始字符串值吗?
  • 是的,因为 LocalizeKey 让我们称其为基本枚举包含键的类型

标签: swift enums


【解决方案1】:

您需要在type 参数上switch 并进行模式匹配:

switch type {
    case .message(let messages): return messages.rawValue
    case .buttons(let buttons): return buttons.rawValue
}

您也可以将此作为LocalizeKey 的扩展:

extension LocalizeKey {
    var keyString: String {
        switch self {
            case .message(let messages): return messages.rawValue
            case .buttons(let buttons): return buttons.rawValue
        }
    }
}

【讨论】:

  • @MohmmadS wvteijlingen 在他的回答中提到了一个代码生成工具,所以我认为写这样的方法不会有问题,不会有任何错别字。至于可读性,大多数人在阅读前几个案例后就会明白你在做什么。
  • 我花了几秒钟点击,:D 感谢您的洞察力,我非常接近这个实现,但我想看看其他人会推荐什么,感谢您的回答伙伴。
【解决方案2】:

您将不得不在某个地方切换。如果只有少数几个“子枚举”,那么手动编写一个开关可能是最简单的:

func keyString(for type: LocalizeKey) {
  switch type {
  case .message(let message):
    print(message.rawValue)
  case .buttons(let button):
    print(button.rawValue)
  }
}

如果您不想手动编写此代码,则必须更改数据结构以使其不再需要,或者使用为您生成样板的code generation tool

【讨论】:

  • 所以毕竟切换是必须的,但是关于枚举的技术问题,您能否提出一种不同或更有效的方法来实现我想要做的事情?
【解决方案3】:

虽然提到的答案确实提供了解决方案,但我会提到方法本身的问题:

此时,每个新案例(键)都必须添加到您的 switch 语句中并带有相关值,这似乎是不受欢迎的样板编码;我假设您可以想象在枚举中有 许多 个案例时会是什么样子。

因此,我建议采用一种更加动态的方法,而不是在 switch 语句中手动添加每个案例的值。示例:

protocol Localizable {
    var value: String { get }
}

extension RawRepresentable where Self: Localizable, Self.RawValue == String {
    var value: String { return rawValue }
}

extension CustomStringConvertible where Self: RawRepresentable, Self.RawValue == String {
    var description: String { return rawValue }
}

struct LocalizeKey {

    enum Buttons: String, Localizable, CustomStringConvertible {
        case remove = "Remove"
        case add = "Add"
    }

    enum Messages: String, Localizable, CustomStringConvertible {
        case success = "Success"
        case failure = "Failure"
    }
}

我们正在为您的代码应用相同的逻辑,并进行了一些改进以使其更易于维护。

基于此,您仍然可以将您的功能实现为:

func keyString(for type: Localizable) {
    print(type)
}

用法:

keyString(for: LocalizeKey.Buttons.add) // Add
keyString(for: LocalizeKey.Messages.success) // Success

IMO,我发现这样称呼它似乎比建议的方法 (keyString(for: .message(.failure))) 更易读、更直接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-05
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多