Here is my version minus the manual abstraction allowing the any keyword to do what it was meant to do. We define a protocol for the data model, City, allowing it to participate in the compiler's existential abstraction. Runs without issue.
import Cocoa
public protocol ManagedFilter: AnyObject {
typealias Condition = ((any DataModel) -> Bool)
var name: String { get }
var condition: Condition? { get }
func extractValues(from array: [any DataModel])
}
public protocol FilterSpecification: ManagedFilter {
associatedtype ValueType: Comparable
var values: [ValueType] { get set }
}
public protocol DataModel {
var code: String { get }
var country: String { get }
var region: String { get }
}
public class FiltersManager {
private var originalArray: [any DataModel]
private var filteredArray: [any DataModel]
private(set) var filters: [any FilterSpecification]
public init(array: [any DataModel], filters: [any FilterSpecification]) {
self.originalArray = array
self.filteredArray = array
self.filters = filters
self.filters.forEach {
$0.extractValues(from: array)
}
}
}
struct City1: DataModel {
let code: String
let country: String
let region: String
}
struct City2: DataModel {
let code: String
let country: String
let region: String
}
class CountryFilter1: FilterSpecification {
var name = "Country"
var values = [String]()
var condition: ((any DataModel) -> Bool)? {
guard !values.isEmpty else { return nil }
return { city in
self.values.contains(city.country)
}
}
func extractValues(from array: [any DataModel]) {
// remove duplicates
}
}
class RegionFilter1: FilterSpecification {
var name = "Region"
var values = [String]()
var condition: ((any DataModel) -> Bool)? {
guard !values.isEmpty else { return nil }
return { city in
self.values.contains(city.region)
}
}
func extractValues(from array: [any DataModel]) {
// remove duplicates
}
}
let cities = [City1(code: "001", country: "US", region: "EST"), City2(code: "002", country: "CA", region: "MST")]
let manager = FiltersManager(array: cities, filters: [CountryFilter1(), RegionFilter1()])