简体   繁体   中英

Swift from generic type to CustomStringConvertible

I've put together the following class (with the help of others in Swift variable comparison where type is not known ).

What I'm trying to achieve is to pass in a closure to SearchOption and when calling getSelectedItemAsString it will run the closure passing in the searchOption as a parameter and return the result.

But because selectedOption is a generic type it's complaining Cannot convert value of type '[T]' to expected argument type '[CustomStringConvertible]' in getSelectedItemAsString()

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

I'm not sure what to do here. The implementation of converting the searchOption to a string will be different for each SearchOption which is why I need the closure.

The full 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 ""
    }

}

The implementation

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

The Error

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

I've managed to solve my problem.

Rather than using a typealias in the implementation I'm defining the type at the same time as the closure:

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

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

}

Then moving the typealias into the class itself with the generic type on the parameter, this ensures that the closure type and searchOption type match:

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM