具有自定义初始化器的Swift枚举将丢失rawValue初始化程序 [英] Swift enum with custom initializer loses rawValue initializer
问题描述
设置
我已经尝试将此问题归结为最简单的形式, 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?
注意
-
Per Swift语言指南:
如果您使用原始值类型定义枚举,枚举将自动接收一个初始值设置,该值为原始值的类型(作为参数
rawValue
),并返回枚举成员或nil
。
-
MyEnum
的自定义初始值设定在扩展中定义,以测试枚举的原始值初始化程序是否被删除,因为以下情况从语言指南。但是,它实现了相同的错误结果。
请注意,如果为值类型定义自定义初始值设置,则将无法再访问到该类型的默认初始化程序(或成员初始化程序,如果它是一个结构)。 [...]
如果您希望使用默认的初始化程序和成员初始化程序以及您自己的自定义初始化程序来初始化自定义值类型,请在扩展名中编写自定义初始值设置,而不是作为$ / $>
将枚举定义移动到
MyClass.swift
解决bar
而不是foo
的错误。
删除自定义初始化程序可以解决两个错误。
一个解决方法是将以下函数包含在枚举定义中并将其用于提供的原始值初始化器。所以似乎添加一个自定义的初始化程序与标记原始值初始化程序
private
相似。init?(raw:Int){
self.init(rawValue:raw)
}
在
MyClass.swift $ c $中明确声明协议符合
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
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 ornil
.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.Moving the enum definition to
MyClass.swift
resolves the error forbar
but not forfoo
.Removing the custom initializer resolves both errors.
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) }
Explicitly declaring protocol conformance to
RawRepresentable
inMyClass.swift
resolves the inline error forbar
, but results in a linker error about duplicate symbols (because raw-value type enums implicitly conform toRawRepresentable
).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屋!