Last active
February 2, 2023 12:47
-
-
Save dkulundzic/ee13d6f15245bbcd7b7cec5b04a8c1cc to your computer and use it in GitHub Desktop.
An example "smart" Collection with embedded filtering abilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public struct FilteringList<Element, Filter>: Collection { | |
public typealias Filtering = (Element, Filter?) -> Bool | |
public typealias Index = Int | |
public typealias Element = Element | |
public var filtering: Filtering? { | |
didSet { filter(using: selectedFilter) } | |
} | |
public var selectedFilter: Filter? { | |
didSet { filter(using: selectedFilter) } | |
} | |
public var elements = [Element]() { | |
didSet { filter(using: selectedFilter) } | |
} | |
private var filteredElements = [Element]() | |
public init( | |
_ elements: [Element] = [], | |
filtering: Filtering? = nil | |
) { | |
self.elements = elements | |
self.filtering = filtering | |
} | |
} | |
public extension FilteringList { | |
var output: [Element] { | |
return selectedFilter == nil ? elements: filteredElements | |
} | |
} | |
// MARK: - Collection | |
public extension FilteringList { | |
subscript(position: Int) -> Element { | |
return filteredElements[position] | |
} | |
var startIndex: Int { | |
return filteredElements.startIndex | |
} | |
var endIndex: Int { | |
return filteredElements.endIndex | |
} | |
func index(after index: Int) -> Int { | |
return filteredElements.index(after: index) | |
} | |
} | |
// MARK: - ExpressibleByArrayLiteral | |
extension FilteringList: ExpressibleByArrayLiteral { | |
public init(arrayLiteral elements: Element...) { | |
self.elements = elements | |
} | |
public typealias ArrayLiteralElement = Element | |
} | |
// MARK: - Private | |
private extension FilteringList { | |
mutating func filter(using selectedFilter: Filter?) { | |
guard let filtering = self.filtering else { | |
filteredElements = elements | |
return SimpleLogger.warning("The filtering closure has not been set. Returning unfiltered elements...") | |
} | |
filteredElements = elements.filter { element -> Bool in | |
return filtering(element, selectedFilter) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment