#swift #string #enums #nested #return-value
#swift #строка #перечисления #вложенный #возвращаемое значение
Вопрос:
РЕШАЕМАЯ
Спасибо @New Dev и @Joakim Danielson за вашу помощь. Я использовал ответ @Joakim Danielson, чтобы улучшить свой код.
У меня есть метод расширения для назначения идентификаторов доступности представлениям на основе заданного строкового перечисления. Я обновил метод, чтобы напрямую принимать случаи перечисления строк в качестве параметра, тем самым ПОЛНОСТЬЮ устраняя необходимость в классе перечисления AccessibilityId, как показано ниже, потрясающе!
Изменения
Перед:
.accessibility(identifier: .home(.clickButton))
// Simplified for StackOverflow.
// Imagine 20 more cases..
enum AccessibilityId {
case home(HomeId)
var rawValue: String {
switch self {
case .home(let id):
return id.rawValue
}
}
}
extension View {
func accessibility(identifier: AccessibilityId) -> ModifiedContent<Self, AccessibilityAttachmentModifier> {
self.accessibility(identifier: identifier.rawValue)
}
}
После:
.accessibility(identifier: HomeId.clickButton)
extension View {
func accessibility<T: RawRepresentable>(identifier: T) -> ModifiedContent<Self, AccessibilityAttachmentModifier> where T.RawValue == String {
self.accessibility(identifier: identifier.rawValue)
}
}
—————————————————————
Оригинальный вопрос
Что у меня есть
enum Item {
case animal(AnimalId)
case vehicle(VehicleId)
case food(FoodId)
var rawValue: String {
switch self {
case .animal(let id):
return id.rawValue
case .vehicle(let id):
return id.rawValue
case .food(let id):
return id.rawValue
}
}
}
enum AnimalId: String {
case cat
case dog
}
// etc.
// Imagine more cases and more enums.
Чего я хочу
enum Item {
case animal(AnimalId)
case vehicle(VehicleId)
case food(FoodId)
var rawValue: String {
switch self {
case self as StringEnum:
return id.rawValue
default:
return ""
}
}
}
Использование
func test() {
foo(.animal(.cat))
foo(.vehicle(.plane))
foo(.food(.tacos))
}
func foo(_ item: Item) {
print(item.rawValue)
}
Я доволен использованием, но я бы хотел уменьшить количество повторяющихся случаев в данном операторе switch . Обратите внимание, как все они имеют return id.rawValue
. Приведенное выше — всего лишь пример, на самом деле у меня около 30 случаев.
Мой вопрос
Есть ли у меня способ перехватить все вложенные строковые перечисления одним переключателем или разрешить регистр, чтобы уменьшить дублирующийся код, который я должен написать, без потери предполагаемого использования?
Спасибо за ваши усилия, я надеюсь найти улучшение для моего кода!
Комментарии:
1. Значит, Animal и AnimalID — это одно и то же?
2. Каковы определения
AnimalId
и тому подобное?3. Ах да, @JoakimDanielson! Мой плохой, я отредактировал свой вопрос, спасибо!
4. @Alexander AnimalID, VehicleId и FoodId — это все строковые перечисления с простыми случаями, такими как «case cat, case dog, case car, case fruit» все, что вы можете себе представить, никаких других переменных или методов, связанных с этим вопросом.
Ответ №1:
Вот решение, которое основано не на том, что Item является перечислением, а на общей структуре
struct Item<T: RawRepresentable> where T.RawValue == String {
let thing: T
var rawValue: String {
thing.rawValue
}
}
С помощью этого решения вам не нужно изменять другие ваши перечисления.
Пример
let item1 = Item(thing: AnimalId.cat)
let item2 = Item(thing: VehicleId.car)
print(item1.rawValue, item2.rawValue)
выводит
cat car
Комментарии:
1. Спасибо вам за ваше предложение, основываясь на нем, мне удалось найти решение для своих нужд. Я обновил свой вопрос / сообщение, чтобы отразить мои изменения! Я принял ваш ответ!
Ответ №2:
Вам нужно что-то общее между всеми этими связанными значениями, например, соответствие общему протоколу, например protocol RawStringValue
:
protocol RawStringValue {
var rawValue: String { get }
}
// String enums already conform without any extra implementation
extension AnimalId: RawStringValue {}
extension VehicleId: RawStringValue {}
extension FoodId: RawStringValue {}
Тогда вы могли бы создать switch self
внутри вот так:
var rawValue: String {
switch self {
case .animal (let id as RawStringValue),
.vehicle (let id as RawStringValue),
.food (let id as RawStringValue):
return id.rawValue
}
}
При этом enum со связанными значениями — не самый удобный тип для работы, поэтому убедитесь, что это правильный выбор.
Комментарии:
1. Спасибо за предложение. Приятно видеть автоматическое соответствие RawStringValue, это приятно. И я рад видеть, что можно позволить случаям провалиться, приведя их к одному и тому же протоколу! Но я пока не удовлетворен. Существует ли тип или класс, к которому можно привести перечисление строк без введения протокола?