Swift 从通用类型到 CustomStringConvertible

Swift from generic type to CustomStringConvertible

我整理了以下 class(在 中其他人的帮助下)。

我想要实现的是将闭包传递给 SearchOption 并且在调用 getSelectedItemAsString 时它将 运行 闭包作为参数传入 searchOption 和 return结果。

但是因为 selectedOption 是一个通用类型,它在 getSelectedItemAsString()

中抱怨 Cannot convert value of type '[T]' to expected argument type '[CustomStringConvertible]'
public func getSelectedItemAsString() -> String {
    if self.searchOptionToString != nil && self.selectedOption != nil {
        return self.searchOptionToString!(selectedOption!)
    }
    return ""
}

我不知道该做什么。将 searchOption 转换为字符串的实现对于每个 SearchOption 都是不同的,这就是我需要闭包的原因。

完整class

public typealias searchOptionToCloudSearchQuery = ([CustomStringConvertible]) -> String

public class SearchOption<T: Equatable> {

    private var title: String
    private var allowAny: Bool
    private var allowMultiple: Bool
    private var dependencies: [SearchOption]?

    private var selectedOption: [T]?

    private var searchOptionToString: searchOptionToCloudSearchQuery?

    init(title: String, allowAny: Bool, allowMultiple: Bool, dependencies: [SearchOption]?) {
        self.title = title
        self.allowAny = allowAny
        self.allowMultiple = allowMultiple
        self.dependencies = dependencies
    }

    public func setSelectedItem(selectedOption: T) -> Void {
        if self.selectedOption == nil || !self.allowMultiple{
            self.selectedOption = [T]()
        }
        self.selectedOption?.append(selectedOption)
    }

    public func getSelectedItem() -> [T]? {
        return self.selectedOption
    }

    public func setSearchOptionToCloudSearchQueryClosure(closure: searchOptionToCloudSearchQuery) -> Void {
        self.searchOptionToString = closure
    }

    public func getSelectedItemAsString() -> String {
        if self.searchOptionToString != nil && self.selectedOption != nil {
            return self.searchOptionToString!(selectedOption!)
        }
        return ""
    }

}

实现

var make: SearchOption = SearchOption<String>(title: "Make", allowAny: true, allowMultiple: true, dependencies: nil)

make.setSelectedItem("Vauxhall")

var closure: searchOptionToCloudSearchQuery = {(selectedOptions) in

    var stringBuilder = ""
    for item in selectedOptions {
        if item is String {
            stringBuilder += item as! String
        }
    }
    return stringBuilder

}

make.setSearchOptionToCloudSearchQueryClosure(closure)
make.getSelectedItemAsString()

错误

Playground execution failed: /var/folders/b5/3jvkp2jd5q5fmps2hrw91781cmf7f_/T/./lldb/570/playground442.swift:38:61: error: cannot convert value of type '[T]' to expected argument type '[CustomStringConvertible]'
            return self.searchOptionToString!(selectedOption!)
                                              ~~~~~~~~~~~~~~^

我已经解决了我的问题。

我没有在实现中使用类型别名,而是在定义闭包的同时定义了类型:

var closure: ([String]) -> String = {(selectedOptions) in

    var stringBuilder = ""
    for item in selectedOptions {
        stringBuilder += item
    }
    return stringBuilder

}

然后将 typealias 移动到 class 本身,并在参数上使用通用类型,这确保了闭包类型和 searchOption 类型匹配:

public class SearchOption<T: Equatable> {

    public typealias searchOptionToCloudSearchQuery = ([T]) -> String

    /.../

    public func getSelectedItemAsString() -> String {
        if self.searchOptionToString != nil && self.selectedOption != nil {
            return self.searchOptionToString!(selectedOption!)
        }
        return ""
    }

}