私はこの問題を次のように最も単純な形に要約しようとしました。
セットアップ
Xcodeバージョン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?'
ノート
パースウィフト言語ガイド:
raw値の型で列挙型を定義すると、列挙型はraw値の型の値を(と呼ばれるパラメーターとして
rawValue
)取り、列挙型メンバーまたはのいずれかを返す初期化子を自動的に受け取りますnil
。のカスタム初期化子
MyEnum
は拡張で定義され、言語ガイドの次のケースにより、列挙型のraw値の初期化子が削除されたかどうかをテストしました。ただし、同じエラー結果が得られます。値型のカスタム初期化子を定義すると、その型のデフォルトの初期化子(または構造体の場合はメンバーごとの初期化子)にアクセスできなくなることに注意してください。[...]
デフォルトの初期化子とメンバーごとの初期化子、および独自のカスタム初期化子を使用してカスタム値型を初期化できるようにする場合は、値型の元の実装の一部としてではなく、拡張でカスタム初期化子を記述します。enum定義を移動して
MyClass.swift
、のエラーを解決しますがbar
、解決しませんfoo
。カスタム初期化子を削除すると、両方のエラーが解決されます。
回避策の1つは、次の関数を列挙型定義に含め、提供された生の値の初期化子の代わりにそれを使用することです。つまり、カスタム初期化子を追加すると、生の値の初期化子をマークするのと同じような効果があるように見えます
private
。init?(raw: Int) { self.init(rawValue: raw) }
プロトコルの準拠を
RawRepresentable
inに明示的に宣言MyClass.swift
すると、のインラインエラーが解決されますがbar
、シンボルの重複に関するリンカエラーが発生します(生の値型の列挙が暗黙的にに準拠するためRawRepresentable
)。extension MyEnum: RawRepresentable {}
誰かがここで何が起こっているのかについてもう少し洞察を提供できますか?raw値のイニシャライザにアクセスできないのはなぜですか?
internal
スコープではなく(または少なくとも型と一致する)スコープが必要ですprivate
。