【问题标题】:Swift: how to set property with an enum using StringSwift:如何使用 String 设置带有枚举的属性
【发布时间】:2021-02-03 14:11:54
【问题描述】:

我正在访问一个返回特定字符串的端点,如下所示:

type: "event type A"

根据我收到的事件类型,我需要在应用程序的另一部分设置一个图标。我想使用枚举来做到这一点。包含图标的元素在 UITableViewCell (HistoryTableViewCell) 的子类中声明如下:

private lazy var type: UIImageView = {
    let imageView = UIImageView()
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.contentMode = .scaleAspectFill
    imageView.tintColor = UIColor.darkGrey
    contentView.addSubview(imageView)
    return imageView
}()

所以我想根据从 API 检索到的值来设置图像。我已经设置了以下枚举:

enum EventType {
    case eventTypeA
    case eventTypeB
    case eventTypeC
    case eventTypeD
    case eventTypeE
    case eventTypeF
}

然后是事件类型变量:

var eventType: EventType {
    willSet {
        switch newValue {
        case .eventTypeA:
            type.image = #imageLiteral(resourceName: "eventA_icon")
        case .eventTypeB:
            type.image = #imageLiteral(resourceName: "eventB_icon")
        case .eventTypeC:
            type.image = #imageLiteral(resourceName: "eventC_icon")
        case .eventTypeD:
            type.image = #imageLiteral(resourceName: "eventD_icon")
        case .eventTypeE:
            type.image = #imageLiteral(resourceName: "eventE_icon")
        case .eventTypeF:
            type.image = #imageLiteral(resourceName: "EventF_icon")
            
        default:
            type.image = #imageLiteral(resourceName: "eventA_icon")
        }
    }
}

但这就是我有点不适应的地方。如何使用我从 API 响应收到的字符串以一种有效的方式使用枚举中的值设置 eventType。

所以在TableViewController(HistoryTableViewController)中我确实设置了另一个切换方法:

private func setEventType(data: HistoryTableViewController.History, cell: HistoryTableViewCell) {
    switch data.type {
    case "event type A":
        cell.eventType = .eventTypeA
    case "event type B":
        cell.eventType = .eventTypeB
    case "event type C":
        cell.eventType = .eventTypeC
    case "event type D":
        cell.eventType = .eventTypeD
    case "event type E":
        cell.eventType = .eventTypeE
    case "event type F":
        cell.eventType = .eventTypeF
    default:
        return
    }
}

历史定义如下:

struct History {
    let type: String?
    ... // more  values here
}

然后我有一个变量数据如下:

var data = [History]()

我是这样调用我的 setEventTypeMethod 的:

setEventType(data: data[indexPath.row], cell: cell)

它可以工作(!),但似乎效率极低,我相信必须有一种更稳定/有效的方法来处理这个问题。

【问题讨论】:

    标签: swift api enums switch-statement


    【解决方案1】:

    你可以让你的枚举有一个关联的值,它是每个事件类型的字符串(为了清楚起见,我缩短了枚举)

    enum EventType: String {
        case eventTypeA = "event type A"
        case eventTypeB = "event type B"
        case eventTypeC = "event type C"
    }
    

    然后像这样使用它

    private func setEventType(data: HistoryTableViewController.History, cell: HistoryTableViewCell) {
        guard let eventType = EventType(rawValue: data.type) else { return }
        cell.eventType = eventType
    }
    

    如果事件类型与代码中的命名非常相似,另一种选择是让关联的值仅作为字符串的唯一部分,并添加一个特殊的 init 来提取该部分

    enum EventType: String {
        case a
        case b
        case c
    
        init?(eventType: String) {
            let value = eventType.sufix(1).lowercased()
            self.init(rawValue: value)
        }
    }
    

    那么这可以用来大大简化你的代码

    private func setEventType(data: HistoryTableViewController.History, cell: HistoryTableViewCell) {
        guard let eventType = EventType(eventType: data.type) else { return }
        cell.eventType = eventType
    }
    
    var eventType: EventType {
        willSet {
            var imageName = "event\(newValue.rawValue.uppercased())_icon"
            type.image = imageLiteral(resourceName: imageName)
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以修改您的枚举以使用 String 的原始值,如下所示:

      enum EventType: String {
          case eventTypeA = "event type A"
          case eventTypeB = "event type B"
          case eventTypeC = "event type C"
          case eventTypeD = "event type D"
          case eventTypeE = "event type E"
          case eventTypeF = "event type F"
      }
      

      那么你的setEventType(data:cell:)会被简化成这样:

      private func setEventType(data: HistoryTableViewController.History, cell: HistoryTableViewCell) {
          guard let type = data.type, let eventType = EventType(rawValue: type) else { return }
          cell.eventType = eventType
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-21
        • 2012-09-22
        • 1970-01-01
        • 1970-01-01
        • 2014-08-30
        • 1970-01-01
        • 2020-03-08
        • 1970-01-01
        相关资源
        最近更新 更多