Swift枚举协议一致性

时间:2020-08-14 00:21:13

标签: swift enums associated-types

我想创建一个我的不同枚举可以遵循的Swift协议,因此我可以在使用枚举的rawValue时使用相同的“类型”。基本上,该协议应如下所示:

protocol SidebarCustomFilter {
    
    var image: UIImage { get }

    var filterPredicate: NSPredicate { get }
}

符合此要求的示例枚举:

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")
    }
}

现在我想在一个结构体中使用这个枚举:

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
    }
}

到目前为止一切顺利。但是,如果我尝试对枚举(上面已描述的协议类型)使用“ rawValue”,则会给我一个错误

sidebarItem.sidebarCustomFilter?.rawValue // Value of type 'SidebarCustomFilter' has no member 'rawValue'

这是有道理的,因为SidebarCustomFilter只是一个协议。但是,如果我尝试使其继承自RawRepresentable(应该允许它与rawValue一起使用),

protocol SidebarCustomFilter: RawRepresentable {
    
    var image: UIImage { get }

    var filterPredicate: NSPredicate { get }
}

我遇到了另一个错误:

var sidebarCustomFilter: SidebarCustomFilter? // Protocol 'SidebarCustomFilter' can only be used as a generic constraint because it has Self or associated type requirements

我相信这与使用RawRepresentable的{​​{1}}有关,但是我不确定如何解决。

那么我如何使我的协议起作用,以使其强制要求只有其他枚举符合它(因此对它使用'rawValue'是有效的)?

1 个答案:

答案 0 :(得分:0)

找到了解决方案:

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
    }
}

现在,我可以使用sidebarItem.sidebarCustomFilter?.name而不是直接要求rawValue,它可以工作!

编辑:添加代码以显示其存储方式:

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
    }
}

及其用法:

let titleString = sidebarItem.sidebarCustomFilter?.name ?? ""
相关问题