简体   繁体   中英

Swift enum protocol conformance

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)?

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 ?? ""

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM