Reputation: 11782
In my code, I have a protocol function search. I want to pass multiple closures that can perform filtering process.
There are few things I am confused. Firstly how to send a generic array of closures into search function. Secondly how will I iterate over each closure to perform the filtering process of each array element.
I have a function
func search(query: String, mainDataList:[T], ____ closuersArray, completionHandler: @escaping ([T]?, Error?) -> Void)
{
let queue = DispatchQueue(label: "SomeQueue", attributes: .concurrent)
queue.asyncAfter(deadline: .now() + 0.3, execute: {
var dataList : [T] = []
// Perform filtering
for clouser in closuersArray {
// Do something here.
}
DispatchQueue.main.async {
completionHandler(dataList, nil)
}
})
}
A couple of random functions as closures are defined as
func containsDataClosuer(query: String, model: T) -> Bool {
// Do something here
return false
}
func someOtherClouser(query: String, model: T) -> Bool {
// Do something here
return false
}
Upvotes: 0
Views: 690
Reputation: 26066
A possible solution:
Initial base:
protocol Searchable {
var titleField: String { get }
var subtitleField: String { get }
var additionalField: String { get }
}
struct Item: CustomStringConvertible {
var title: String
var subtitle: String
var additional: String
var description: String {
return "<Item>: T: \(title) - S: \(subtitle) - A: \(additional)"
}
}
extension Item: Searchable {
var titleField: String { title }
var subtitleField: String { subtitle }
var additionalField: String { additional }
}
let initialList: [Item] = [Item(title: "First Title", subtitle: "First Subtitle", additional: "First Add"),
Item(title: "Second Title", subtitle: "Second Subtitle", additional: "Second Add pp"),
Item(title: "Third Title", subtitle: "Third Subtitle", additional: "Third Add"),
Item(title: "Fourth Title", subtitle: "Fourth Subtitle", additional: "Fourth Add")]
Search Parameters, with either functions (since you seem to want func
), or closures
(and not clouser
as you write it, but which aren't really closures in your case)
var closureTitle: ((String, Searchable) -> Bool)
closureTitle = { searchText, aSearchable in
return aSearchable.titleField.contains(searchText)
}
var closureSubtitle: ((String, Searchable) -> Bool)
closureSubtitle = { searchText, aSearchable in
return aSearchable.subtitleField.contains(searchText)
}
func functionAdditional(_ searchText: String, _ aSearchable: Searchable) -> Bool {
return aSearchable.additionalField.contains(searchText)
}
Your main search function:
func search<T: Searchable>(query: String, mainDataList:[T], filters: [((String, T) -> Bool)], completionHandler: @escaping ([T], Error?) -> Void)
{
let queue = DispatchQueue(label: "SomeQueue", attributes: .concurrent)
queue.asyncAfter(deadline: .now() + 0.3, execute: {
//The logic:
// We do a clasic `filter` call on mainDataList
// For each item inside it, we check if at least one of the filters allows it
// If yes, we keep it (return true), else, we discard it (return false)
// That's a OR logic: If you find the search text query in ANY of three properties
// If you want an AND (meaning, text has to be present in EACH property to be valid), change the `contains` with
`filters.allSatisfy { aFilter in aFilter(query, aSearchable) }` which should do the trick
let filteredList = mainDataList.filter { aSearchable in
let keepElement = filters.contains { aFilter in
aFilter(query, aSearchable) == true
}
return keepElement
}
DispatchQueue.main.async {
completionHandler(filteredList, nil)
}
})
}
In use:
//With only closures
search(query: "o", mainDataList: initialList, filters: [closureTitle, closureSubtitle]) { filteredList, error in
print("Only closures: \(filteredList)")
}
//With closures and functions
search(query: "pp", mainDataList: initialList, filters: [closureTitle, closureSubtitle, functionAdditional]) { filteredList, error in
print("Closures & Functions: \(filteredList)")
}
Output:
$>Only closures: [<Item>: T: Second Title - S: Second Subtitle - A: Second Add pp, <Item>: T: Fourth Title - S: Fourth Subtitle - A: Fourth Add]
$>Closures & Functions: [<Item>: T: Second Title - S: Second Subtitle - A: Second Add pp]
Upvotes: 1