在 swift 函数中传递多个闭包并执行过滤

Passing multiple closures in swift function and perform filtering

在我的代码中,我有一个协议函数搜索。我想传递多个可以执行过滤过程的闭包。

有几件事让我感到困惑。 首先,如何将通用的闭包数组发送到搜索函数中。其次,我将如何遍历每个闭包来执行每个数组元素的过滤过程。

我有一个功能

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

作为闭包的几个随机函数定义为

    func containsDataClosuer(query: String, model: T) -> Bool {
       // Do something here
       return false
    }
    
    func someOtherClouser(query: String, model: T) -> Bool {
       // Do something here
       return false
}

可能的解决方案:

初始基地:

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]