【问题标题】:Overriding Enum init?(rawValue: String) to not be optional覆盖 Enum init?(rawValue: String) 不是可选的
【发布时间】:2016-05-09 06:16:48
【问题描述】:

如果 rawValue init 将返回 nil,我希望在 Swift 中为我的枚举从 rawValue 初始化以返回默认值。 现在我有这样的东西:

public init(fromRawValue: String){
        self = Language(rawValue: fromRawValue) ?? .English
}

我不喜欢这个,因为它是全新的初始化程序。 我试着做这样的事情:

public init(rawValue: String){
        self = Language(rawValue: fromRawValue) ?? .English
}

但是我遇到了运行时异常,但访问权限不正确。我能不能让它工作,或者我只需要使用这个新的,我不能覆盖原来的不是可选的?

我想知道是否可以从 rawValue 覆盖原始初始化,而不是使用可失败初始化的全新初始化。

【问题讨论】:

标签: ios swift enums initialization


【解决方案1】:

默认初始化程序是failable。这意味着如果接收到的参数与有效的枚举大小写不匹配,它会返回nil

现在你想做两件不相容的事情:

  1. 您希望重新定义默认初始化程序,使其不会失败。实际上,您希望在接收到的参数无效时创建一个默认枚举值。
  2. 在您重新定义的初始化程序中,您希望使用与新初始化程序相同的名称调用可失败初始化程序(不再存在)。

这是不可能的,我有以下3种可能的解决方案:

  1. 创建不同的初始化

你定义了一个新的不可失败初始化器,它有一个默认值,一个不同的参数名,在里面你调用默认的可失败初始化器。

enum Language: String {
    
    case english = "English", italian = "Italian", french = "French"
    
    init(fromRawValue: String) {
        self = Language(rawValue: fromRawValue) ?? .english
    }
}
  1. 重新定义默认初始化

您重新定义默认初始化程序,使其不会失败,并在其中编写完整的逻辑。

enum Language: String {
    
    case english = "English", italian = "Italian", french = "French"
    
    init(rawValue: String) {
        switch rawValue {
        case "Italian": self = .italian
        case "French": self = .french
        default: self = .english
        }
    }
}
  1. 创建静态函数
enum Language: String {

    case english = "English", italian = "Italian", french = "French"

    static func build(rawValue: String) -> Language {
        return Language(rawValue: rawValue) ?? .english
    }
}

现在您可以构建Language 值写入:

let italian = Language.build(rawValue: "Italian") // Italian
let defaultValue = Language.build(rawValue: "Wrong input") // English

【讨论】:

  • 很棒的答案。 “self = ...”是无价的。这个语言中各种隐藏的 Swift 掘金 :)
  • 您可以将方法 #1 的初始化程序中的 Language 替换为 type(of: self).init 以获得更通用的方法。
【解决方案2】:

在 Luca 的重新定义默认 init 的解决方案中,可以额外将 rawValue 参数类型设为可选,这样可以在数据源不可靠时减少调用站点的一些代码。

enum PrecipitationType: String {
    case rain, snow, sleet, none

    typealias RawValue = String

    init(rawValue: String?) {
        guard let rawValue = rawValue else { self = .none; return }

        switch rawValue {
            case PrecipitationType.rain.rawValue: self = .rain
            case PrecipitationType.snow.rawValue: self = .snow
            case PrecipitationType.sleet.rawValue: self = .sleet
            default: self = .none
        }
    }
}

当我最初尝试这个时,它产生了多个错误。关键是重新定义 RawValue 类型别名以保持与 RawRepresentable 的一致性。

【讨论】:

    猜你喜欢
    • 2017-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多