提问者:小点点

已解决-Swift枚举-将嵌套枚举转换为字符串枚举以允许. rawValue


感谢@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语句中重复案例的数量。注意它们都是如何返回id. rawValue的。上面只是一个例子,实际上我有大约30个案例。

有没有办法让我在一个开关中捕获所有嵌套字符串枚举,或者让案例减少我必须编写的重复代码而不会失去预期的用法?

谢谢你的努力,我希望能为我的代码找到改进!


共2个答案

匿名用户

这是一个解决方案,它不是基于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)

产出

猫车

匿名用户

您需要所有这些关联值之间的共同点,例如与共享协议的一致性,例如协议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
   }
}

话虽如此,带有关联值的枚举不是最方便使用的类型,因此请确保它是正确的选择。