Saya telah mencoba meringkas masalah ini ke bentuk yang paling sederhana dengan berikut ini.
Mempersiapkan
Versi Xcode 6.1.1 (6A2008a)
Enum yang ditentukan di 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
}
}
}
dan kode yang menginisialisasi enum di file lain, 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")
}
}
Kesalahan
Xcode memberi saya kesalahan berikut ketika mencoba menginisialisasi MyEnum
dengan penginisialisasi nilai mentahnya:
Cannot convert the expression's type '(rawValue: IntegerLiteralConvertible)' to type 'MyEnum?'
Catatan
Sesuai Panduan Bahasa Swift :
Jika Anda mendefinisikan enumerasi dengan tipe nilai mentah, enumerasi secara otomatis menerima penginisialisasi yang mengambil nilai tipe nilai mentah (sebagai parameter yang dipanggil
rawValue
) dan mengembalikan anggota enumerasi ataunil
.Penginisialisasi khusus untuk
MyEnum
ditentukan dalam ekstensi untuk menguji apakah penginisialisasi nilai mentah enum telah dihapus karena kasus berikut dari Panduan Bahasa . Namun, itu mencapai hasil kesalahan yang sama.Perhatikan bahwa jika Anda menentukan penginisialisasi ubahsuaian untuk suatu jenis nilai, Anda tidak akan lagi memiliki akses ke penginisialisasi default (atau penginisialisasi beranggota, jika itu adalah struktur) untuk jenis itu. [...]
Jika Anda ingin jenis nilai khusus Anda dapat diinisialisasi dengan penginisialisasi default dan penginisialisasi sesuai anggota, dan juga dengan penginisialisasi khusus Anda sendiri, tulis penginisialisasi kustom Anda dalam ekstensi, bukan sebagai bagian dari penerapan asli jenis nilai.Memindahkan definisi enum untuk
MyClass.swift
menyelesaikan error untukbar
tetapi tidak untukfoo
.Menghapus penginisialisasi kustom menyelesaikan kedua kesalahan.
Salah satu solusinya adalah dengan menyertakan fungsi berikut dalam definisi enum dan menggunakannya sebagai pengganti penginisialisasi nilai mentah yang disediakan. Jadi, sepertinya menambahkan penginisialisasi khusus memiliki efek yang mirip dengan menandai penginisialisasi nilai mentah
private
.init?(raw: Int) { self.init(rawValue: raw) }
Mendeklarasikan kesesuaian protokol secara eksplisit ke
RawRepresentable
dalamMyClass.swift
menyelesaikan error sebaris untukbar
, tetapi menghasilkan error linker tentang simbol duplikat (karena enum tipe nilai mentah secara implisit menyesuaikan denganRawRepresentable
).extension MyEnum: RawRepresentable {}
Adakah yang bisa memberikan lebih banyak wawasan tentang apa yang terjadi di sini? Mengapa penginisialisasi nilai mentah tidak dapat diakses?
internal
cakupan (atau setidaknya cocok dengan jenisnya), bukanprivate
.Jawaban:
Bug ini diselesaikan di Xcode 7 dan Swift 2
sumber
Dalam kasus Anda, ini akan menghasilkan ekstensi berikut:
sumber
Anda bahkan dapat membuat kode lebih sederhana dan berguna tanpa
switch
case, dengan cara ini Anda tidak perlu menambahkan case lagi saat Anda menambahkan tipe baru.sumber
Ya, ini adalah masalah yang mengganggu. Saat ini saya sedang mengerjakannya menggunakan fungsi cakupan global yang bertindak sebagai pabrik, yaitu
sumber
Ini berfungsi untuk Swift 4 di Xcode 9.2 bersama dengan EnumSequence saya :
Keluaran
sumber
Tambahkan ini ke kode Anda:
sumber