Swift从泛型类型到CustomStringConvertible

时间:2015-10-01 14:27:34

标签: swift generics closures

我将以下课程(在Swift variable comparison where type is not known中的其他人的帮助下)放在一起。

我想要实现的是将一个闭包传递给SearchOption,当调用getSelectedItemAsString时,它将运行闭包传递searchOption作为参数并返回结果。

但由于selectedOption是一般类型,因此Cannot convert value of type '[T]' to expected argument type '[CustomStringConvertible]'

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

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

完整的课程

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!)
                                              ~~~~~~~~~~~~~~^

1 个答案:

答案 0 :(得分:1)

我设法解决了我的问题。

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

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

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

}

然后使用参数上的泛型类型将类型移动到类本身中,这可确保闭包类型和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 ""
    }

}