Reputation: 7511
I want to create a Swift protocol that my different enums can conform to, so I can use the same 'type' while utilizing the enum's rawValue. Basically, the protocol should look like this:
protocol SidebarCustomFilter {
var image: UIImage { get }
var filterPredicate: NSPredicate { get }
}
An example enum that conforms to this:
enum SidebarFilterLogs : String, CaseIterable, SidebarCustomFilter{
case filterAll = "All"
case filterThisWeek = "This Week"
var image: UIImage {
return UIImage(systemName: "tray.full.fill")!
}
var filterPredicate: NSPredicate {
return NSPredicate.init(format: "TRUEPREDICATE")
}
}
Now I want to use this enum inside a struct:
struct CJSidebarFilterItem: Hashable {
private var identifier: String = ""
var sectionType: SectionType
var sidebarCustomFilter: SidebarCustomFilter?
init(logsFilter: SidebarFilterLogs) {
self.sectionType = .filters
self.sidebarCustomFilter = logsFilter
self.identifier = UUID().uuidString
}
func hash(into hasher: inout Hasher) {
hasher.combine(identifier)
}
static func == (lhs: CJSidebarFilterItem, rhs: CJSidebarFilterItem) -> Bool {
return lhs.identifier == rhs.identifier
}
}
So far so good. However, if I try to use the 'rawValue' for the enum (of the protocol type I've described above), it gives me an error
sidebarItem.sidebarCustomFilter?.rawValue // Value of type 'SidebarCustomFilter' has no member 'rawValue'
That makes sense, since the SidebarCustomFilter
is only a protocol. However, if I try to make it inherit from RawRepresentable (which should allow it to work with rawValue
),
protocol SidebarCustomFilter: RawRepresentable {
var image: UIImage { get }
var filterPredicate: NSPredicate { get }
}
I get a different error:
var sidebarCustomFilter: SidebarCustomFilter? // Protocol 'SidebarCustomFilter' can only be used as a generic constraint because it has Self or associated type requirements
I believer this has something to do with RawRepresentable
using an associatedtype RawValue
, but I'm not sure how to resolve it.
So how do I get my protocol to work such that it enforces that only other enums are conforming to it (and hence it's valid to use 'rawValue' against it)?
Upvotes: 0
Views: 1522
Reputation: 7511
Found a solution:
protocol SidebarCustomFilter {
var name: String { get }
var image: UIImage { get }
var filterPredicate: NSPredicate { get }
}
extension SidebarCustomFilter where Self: RawRepresentable {
var name: Self.RawValue {
return self.rawValue
}
}
Now I can use sidebarItem.sidebarCustomFilter?.name
instead of directly asking for the rawValue
, and it works!
EDIT: adding code to show how it's stored:
struct CJSidebarFilterItem: Hashable {
private var identifier: String = ""
var sectionType: SectionType
var sidebarCustomFilter: SidebarCustomFilter? // storing as generic type
init(logsFilter: SidebarFilterLogs) {
self.sectionType = .filters
self.sidebarCustomFilter = logsFilter
self.identifier = UUID().uuidString
}
func hash(into hasher: inout Hasher) {
hasher.combine(identifier)
}
static func == (lhs: CJSidebarFilterItem, rhs: CJSidebarFilterItem) -> Bool {
return lhs.identifier == rhs.identifier
}
}
and how it's used:
let titleString = sidebarItem.sidebarCustomFilter?.name ?? ""
Upvotes: 1