我试图将此问题归结为最简单的形式,如下所示。
Xcode Version 6.1.1(6A2008a)
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
}
}
}
以及在另一个文件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")
}
}
尝试使用原始值初始化程序初始化MyEnum
时,Xcode给出了以下错误:
Cannot convert the expression's type '(rawValue: IntegerLiteralConvertible)' to type 'MyEnum?'
如果使用原始值类型定义枚举,则枚举会自动接收初始值设定项,该初始值设定项接受原始值类型的值(作为名为
rawValue
的参数)并返回枚举成员或{{ 1}}。
nil
的自定义初始化程序在扩展程序中定义,用于测试是否因为the Language Guide中的以下情况而删除了枚举的原始值初始值设定项。但是,它会产生相同的错误结果。
请注意,如果为值类型定义自定义初始值设定项,则您将无法再访问该类型的默认初始值设定项(或成员初始值设定项,如果它是结构)。 [...]
如果您希望使用默认初始化程序和成员初始化程序以及您自己的自定义初始化程序初始化您的自定义值类型,请在扩展名中编写自定义初始值设定项,而不是作为值类型的原始实现的一部分。
将枚举定义移至MyEnum
可解决MyClass.swift
的错误,但不会解决bar
的错误。
删除自定义初始值设定项可解决这两个错误。
一种解决方法是在枚举定义中包含以下函数,并使用它代替提供的原始值初始值设定项。因此,似乎添加自定义初始值设定项与标记原始值初始值设定项foo
具有类似的效果。
private
在init?(raw: Int) {
self.init(rawValue: raw)
}
中明确声明与RawRepresentable
的协议一致性解决了MyClass.swift
的内联错误,但导致链接器出现重复符号错误(因为原始值类型枚举隐式符合bar
)。
RawRepresentable
任何人都可以更深入地了解这里发生了什么吗?为什么原始值初始化程序不可访问?
答案 0 :(得分:23)
此错误在Xcode 7和Swift 2中解决
答案 1 :(得分:13)
extension TemplateSlotType {
init?(rawString: String) {
// Check if string contains 'carrousel'
if rawString.rangeOfString("carrousel") != nil {
self.init(rawValue:"carrousel")
} else {
self.init(rawValue:rawString)
}
}
}
在您的情况下,这将导致以下扩展名:
extension MyEnum {
init?(string: String) {
switch string.lowercaseString {
case "zero":
self.init(rawValue:0)
case "one":
self.init(rawValue:1)
case "two":
self.init(rawValue:2)
default:
return nil
}
}
}
答案 2 :(得分:6)
如果没有GalenTestNgTestBase
个案例,您甚至可以使代码更简单实用,这样您在添加新类型时就不需要添加更多案例。
switch
答案 3 :(得分:1)
Yeah this is an annoying issue. I'm currently working around it using a global-scope function that acts as a factory, i.e.
worldpopulationlist.add(map);
答案 4 :(得分:0)
这适用于Xcode 9.2上的Swift 4以及我的EnumSequence:
enum Word: Int, EnumSequenceElement, CustomStringConvertible {
case apple, cat, fun
var description: String {
switch self {
case .apple:
return "Apple"
case .cat:
return "Cat"
case .fun:
return "Fun"
}
}
}
let Words: [String: Word] = [
"A": .apple,
"C": .cat,
"F": .fun
]
extension Word {
var letter: String? {
return Words.first(where: { (_, word) -> Bool in
word == self
})?.key
}
init?(_ letter: String) {
if let word = Words[letter] {
self = word
} else {
return nil
}
}
}
for word in EnumSequence<Word>() {
if let letter = word.letter, let lhs = Word(letter), let rhs = Word(letter), lhs == rhs {
print("\(letter) for \(word)")
}
}
输出
A for Apple
C for Cat
F for Fun
答案 5 :(得分:-1)
将此添加到您的代码中:
extension MyEnum {
init?(rawValue: Int) {
switch rawValue {
case 0: self = .Zero
case 1: self = .One
case 2: self = .Two
default: return nil
}
}
}