具有自定义初始化器的Swift枚举将丢失rawValue初始化程序 [英] Swift enum with custom initializer loses rawValue initializer

查看:220
本文介绍了具有自定义初始化器的Swift枚举将丢失rawValue初始化程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



设置



我已经尝试将此问题归结为最简单的形式, Xcode Version 6.1.1(6A2008a)



MyEnum.swift中定义的枚举

 内部枚举MyEnum:Int {
case Zero = 0,One,Two
}

extension MyEnum {
init?(string:String){
switch string.lowercaseString {
casezero:self = .Zero
caseone:self = .One
casetwo:self = .Two
default:return nil
}
}
}

和代码,用于初始化另一个文件中的枚举, MyClass.swift

 内部类MyClass {
let foo = MyEnum(rawValue:0)//错误
让fooStr = MyEnum(string:zero)

func testFunc(){
let bar = MyEnum(rawValue:1)//错误
let barStr = MyEnum(string:one)

}



错误



Xcode尝试使用其原始值初始化器初始化 MyEnum 时,会出现以下错误:

 无法将表达式的类型(rawValue:IntegerLiteralConvertible)转换为MyEnum?



注意




  1. Per Swift语言指南


    如果您使用原始值类型定义枚举,枚举将自动接收一个初始值设置,该值为原始值的类型(作为参数 rawValue ),并返回枚举成员或 nil



  2. MyEnum 的自定义初始值设定在扩展中定义,以测试枚举的原始值初始化程序是否被删除,因为以下情况从语言指南。但是,它实现了相同的错误结果。


    请注意,如果为值类型定义自定义初始值设置,则将无法再访问到该类型的默认初始化程序(或成员初始化程序,如果它是一个结构)。 [...]

    如果您希望使用默认的初始化程序和成员初始化程序以及您自己的自定义初始化程序来初始化自定义值类型,请在扩展名中编写自定义初始值设置,而不是作为$ / $>

  3. 将枚举定义移动到 MyClass.swift 解决 bar 而不是 foo 的错误。


  4. 删除自定义初始化程序可以解决两个错误。


  5. 一个解决方法是将以下函数包含在枚举定义中并将其用于提供的原始值初始化器。所以似乎添加一个自定义的初始化程序与标记原始值初始化程序 private 相似。

      init?(raw:Int){
    self.init(rawValue:raw)
    }


  6. MyClass.swift RawRepresentable c>解析 bar 的内联错误,但会导致关于重复符号的链接器错误(因为原始值类型枚举隐含地符合 RawRepresentable )。

     扩展名MyEnum:RawRepresentable {} 
    pre>

任何人都可以更加深入了解这里发生了什么?为什么原始值初始化程序不可访问?

解决方案

这个错误在Xcode 7和Swift 2中得到解决


I have tried to boil this issue down to its simplest form with the following.

Setup

Xcode Version 6.1.1 (6A2008a)

An enum defined in MyEnum.swift:

internal enum MyEnum: Int {
    case Zero = 0, One, Two
}

extension MyEnum {
    init?(string: String) {
        switch string.lowercaseString {
        case "zero": self = .Zero
        case "one": self = .One
        case "two": self = .Two
        default: return nil
        }
    }
}

and code that initializes the enum in another file, MyClass.swift:

internal class MyClass {
    let foo = MyEnum(rawValue: 0)  // Error
    let fooStr = MyEnum(string: "zero")

    func testFunc() {
        let bar = MyEnum(rawValue: 1)  // Error
        let barStr = MyEnum(string: "one")
    }
}

Error

Xcode gives me the following error when attempting to initialize MyEnum with its raw-value initializer:

Cannot convert the expression's type '(rawValue: IntegerLiteralConvertible)' to type 'MyEnum?'

Notes

  1. Per the Swift Language Guide:

    If you define an enumeration with a raw-value type, the enumeration automatically receives an initializer that takes a value of the raw value’s type (as a parameter called rawValue) and returns either an enumeration member or nil.

  2. The custom initializer for MyEnum was defined in an extension to test whether the enum's raw-value initializer was being removed because of the following case from the Language Guide. However, it achieves the same error result.

    Note that if you define a custom initializer for a value type, you will no longer have access to the default initializer (or the memberwise initializer, if it is a structure) for that type. [...]
    If you want your custom value type to be initializable with the default initializer and memberwise initializer, and also with your own custom initializers, write your custom initializers in an extension rather than as part of the value type’s original implementation.

  3. Moving the enum definition to MyClass.swift resolves the error for bar but not for foo.

  4. Removing the custom initializer resolves both errors.

  5. One workaround is to include the following function in the enum definition and use it in place of the provided raw-value initializer. So it seems as if adding a custom initializer has a similar effect to marking the raw-value initializer private.

    init?(raw: Int) {
        self.init(rawValue: raw)
    }
    

  6. Explicitly declaring protocol conformance to RawRepresentable in MyClass.swift resolves the inline error for bar, but results in a linker error about duplicate symbols (because raw-value type enums implicitly conform to RawRepresentable).

    extension MyEnum: RawRepresentable {}
    

Can anyone provide a little more insight into what's going on here? Why isn't the raw-value initializer accessible?

解决方案

This bug is solved in Xcode 7 and Swift 2

这篇关于具有自定义初始化器的Swift枚举将丢失rawValue初始化程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆