Mengganti Enum init?(rawValue: String) menjadi tidak opsional

Saya ingin memiliki init dari rawValue untuk enum saya di Swift untuk mengembalikan nilai default jika rawValue init akan mengembalikan nihil. Saat ini saya memiliki sesuatu seperti ini:

public init(fromRawValue: String){
        self = Language(rawValue: fromRawValue) ?? .English
}

Saya tidak suka ini karena ini inisialisasi yang benar-benar baru. Saya mencoba membuat sesuatu seperti ini:

public init(rawValue: String){
        self = Language(rawValue: fromRawValue) ?? .English
}

Tapi saya mendapat pengecualian runtime dengan akses buruk. Dapatkah saya membuatnya berfungsi atau saya hanya perlu menggunakan yang baru ini dan saya tidak dapat mengganti yang asli agar tidak menjadi opsional?

Saya ingin tahu apakah mungkin untuk mengganti init asli dari rawValue bukan solusi dengan yang benar-benar baru yang menggunakan yang bisa gagal.


person Prettygeek    schedule 31.01.2016    source sumber
comment
Kemungkinan duplikat dari Penginisialisasi enum yang tidak dapat gagal dengan nilai default   -  person Kevin    schedule 01.02.2016


Jawaban (2)


Penginisialisasi default adalah failable. Artinya, jika parameter yang diterima tidak cocok dengan kasus enum yang valid, maka parameter tersebut akan mengembalikan nil.

Sekarang Anda ingin melakukan 2 hal yang tidak kompatibel:

  1. Anda ingin mendefinisikan ulang penginisialisasi default agar tidak dapat gagal. Sebenarnya Anda ingin nilai enum default dibuat ketika parameter yang diterima tidak valid.
  2. Di dalam penginisialisasi yang telah didefinisikan ulang, Anda ingin memanggil penginisialisasi yang gagal (yang sudah tidak ada lagi) menggunakan nama yang sama dengan penginisialisasi baru.

Ini tidak mungkin, saya punya 3 kemungkinan solusi sebagai berikut:

1) Membuat init

Anda mendefinisikan penginisialisasi baru yang tidak dapat gagal dengan nilai default, nama parameter yang berbeda, dan di dalamnya Anda memanggil penginisialisasi gagal default.

enum Language: String {

    case english = "English", italian = "Italian", french = "French"

    init(fromRawValue: String){
        self = Language(rawValue: fromRawValue) ?? .english
    }
}

2) Mendefinisikan ulang init default

Anda mendefinisikan ulang penginisialisasi default, membuatnya tidak dapat gagal dan Anda menulis logika lengkap di dalamnya.

enum Language: String {

    case english = "English", italian = "Italian", french = "French"

    init(rawValue: String) {
        switch rawValue {
        case "Italian": self = .italian
        case "French": self = .french
        default: self = .english
        }
    }
}

3) Membuat fungsi statis

enum Language: String {

    case english = "English", italian = "Italian", french = "French"

    static func build(rawValue: String) -> Language {
        return Language(rawValue: rawValue) ?? .english
    }
}

Sekarang Anda dapat membuat nilai Language dengan menulis:

let italian = Language.build(rawValue: "Italian") // Italian
let defaultValue = Language.build(rawValue: "Wrong input") // English
person Luca Angeletti    schedule 01.02.2016
comment
Jawaban yang fantastis. Diri = ... sangat berharga. Segala macam nugget Swift yang tersembunyi di bahasa ini :) - person Marchy; 23.03.2017
comment
Anda dapat mengganti Language dalam penginisialisasi pendekatan #1 menjadi type(of: self).init untuk pendekatan yang lebih umum. - person shim; 30.08.2018

Menambah solusi Luca untuk mendefinisikan ulang init default, dimungkinkan untuk membuat tambahan tipe parameter rawValue opsional, yang mengurangi beberapa kode di situs panggilan ketika sumber data tidak dapat diandalkan.

enum PrecipitationType: String {
    case rain, snow, sleet, none

    typealias RawValue = String

    init(rawValue: String?) {
        guard let rawValue = rawValue else { self = .none; return }

        switch rawValue {
            case PrecipitationType.rain.rawValue: self = .rain
            case PrecipitationType.snow.rawValue: self = .snow
            case PrecipitationType.sleet.rawValue: self = .sleet
            default: self = .none
        }
    }
}

Ketika saya pertama kali mencobanya, ini menghasilkan banyak kesalahan. Kuncinya adalah mendefinisikan ulang typealias RawValue untuk menjaga kesesuaian dengan RawRepresentable.

person Nathan Hosselton    schedule 05.08.2017