Reputation: 1565
I'm hitting an endpoint which returns a specific String as follows:
type: "event type A"
Depending on the event type I receive I need to set an icon in another part of the app. I wanted to do this using an enum. The element which contains the icon is declared in a class which subclasses UITableViewCell (HistoryTableViewCell) as follows:
private lazy var type: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
imageView.tintColor = UIColor.darkGrey
contentView.addSubview(imageView)
return imageView
}()
So I want to set the image depending on the value retrieved from the API. I had set up the following enum:
enum EventType {
case eventTypeA
case eventTypeB
case eventTypeC
case eventTypeD
case eventTypeE
case eventTypeF
}
Then an event type variable:
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")
}
}
}
But this is where I came a little unstuck. How to set eventType with a value from the enum using the String I receive from the API response in an efficient manner.
So in the TableViewController (HistoryTableViewController) I did set up another switch method:
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
}
}
History is defined as follows:
struct History {
let type: String?
... // more values here
}
And then I have a variable data as follows:
var data = [History]()
And I was calling my setEventTypeMethod like this:
setEventType(data: data[indexPath.row], cell: cell)
It works (!) but seems hideously inefficient and I'm sure there must be a more stable / effective way of handling this.
Upvotes: 1
Views: 618
Reputation: 51973
You can let your enum have an associated value that is the string for each event type (I shortened the enum for clarity)
enum EventType: String {
case eventTypeA = "event type A"
case eventTypeB = "event type B"
case eventTypeC = "event type C"
}
and then use it like this
private func setEventType(data: HistoryTableViewController.History, cell: HistoryTableViewCell) {
guard let eventType = EventType(rawValue: data.type) else { return }
cell.eventType = eventType
}
Another option if the event types are so similar named as in your code is to let the associated value to only be the unique part of the string and add a special init to extract that part
enum EventType: String {
case a
case b
case c
init?(eventType: String) {
let value = eventType.sufix(1).lowercased()
self.init(rawValue: value)
}
}
Then this can be used to simplify your code a lot
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)
}
}
Upvotes: 1
Reputation: 8337
You can modify your enum to use raw value of String
, like this:
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"
}
Then your setEventType(data:cell:)
will be simplified to this:
private func setEventType(data: HistoryTableViewController.History, cell: HistoryTableViewCell) {
guard let type = data.type, let eventType = EventType(rawValue: type) else { return }
cell.eventType = eventType
}
Upvotes: 1