一个可能的解决方案:
初始基地:
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")]
搜索参数,使用函数(因为您似乎想要func)或closures(而不是您编写的clouser,但在您的情况下并不是真正的闭包)
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)
}
您的主要搜索功能:
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)
}
})
}
使用中:
//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)")
}
输出:
$>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]