Получение статических переменных из строки - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть следующий класс, который описывает страну:

class Country: NSObject {

    public var name: String

    static let england = Country(name: "England")
    static let scotland = Country(name: "Scotland")
    static let allCountries = [england, scotland]

    init(name: String) {
        self.name = name
        super.init()
    }

    convenience init?(named name: String) {
        guard let country = Country.allCountries.filter( { $0.name == name } ).first else { return nil }
        self.init(name: country.name)
    }

}

Чтобы получить постоянную Country.england, я бы использовал:

let england = Country.england

Однако , я хочу иметь возможность получить эту константу из String, используя convenience init?(named name: String) следующим образом:

let england = Country(named: "England")

Это кажется немного неуклюжим, и этот код инициализирует новый экземпляр "england", а не статический.

Есть ли более Swifty способ сделать это? В идеале я хотел бы просто разрешить self = country в функции convenience init?(named name: String), но я получаю ошибку, которую нельзя присвоить значению: «Я» является неизменным .

Спасибо за любую помощь.

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

А как насчет написания named фабричного метода?

static func named(_ name: String) -> Country? {
    return Country.allCountries.first(where: { $0.name == name } )
}

// usage:
let england = Country.named("England")!

Подход инициализатора можно было бы использовать, если бы Country была структурой:

struct Country {

    public var name: String

    static let england = Country(name: "England")
    static let scotland = Country(name: "Scotland")
    static let allCountries = [england, scotland]

    init(name: String) {
        self.name = name
    }

    init?(named name: String) {
        guard let country = Country.allCountries.filter( { $0.name == name } ).first else { return nil }
        self = country
    }

}
0 голосов
/ 03 сентября 2018

Если у вашего Country есть только name, вам лучше использовать enum ...

enum Country: String, CaseIterable {
    case england = "England"
    case scotland = "Scotland"
}

Country(rawValue: "Scotland") // Optional(scotland)
Country(rawValue: "Wales")    // nil

Примечание CaseIterable - это Swift 4.2+, но позволяет писать Country.allCases

Country.allCases  // [england, scotland]
...