我正在尝试使用Swift中的泛型分解方法。我的方法如下:
func searchFoo(searchText: String?, completion: @escaping ([Foo]?, Error?) -> ()) {
let index = "foo" // <- How can I assign this from a generic type?
searchClient.search(index, searchText) { (json, error) in
if let json = json {
completion(self.fooFrom(json: json), nil)
} else if let error = error {
completion(nil, error)
} else {
completion([], nil)
}
}
}
func searchBar(searchText: String?, completion: @escaping ([Bar]?, Error?) -> ()) {
let index = "bar" // <- How can I assign this from a generic type?
searchClient.search(index, searchText) { (json, error) in
if let json = json {
completion(self.barFrom(json: json), nil)
} else if let error = error {
completion(nil, error)
} else {
completion([], nil)
}
}
}
这两个函数看起来像是一个很好的泛型用例,但我无法弄清楚如何打开泛型类型来获取2个必需的字符串。
当然,我可以将索引名称放在函数签名中,但我觉得它是多余的,因为索引名称是由实际使用的泛型类型暗示的,它可能是bug的来源。
我觉得我错过了一些东西,因为我可能还没有认为Swift方式,所以欢迎任何帮助以获得对此代码的良好重构。
答案 0 :(得分:2)
您可以通过创建协议来实现此目的:
protocol Baz {
static var index: String { get }
static func loadFromJSON(json: JSONObject) -> [Self]
}
然后扩展Foo
和Bar
以符合此协议。最后,为搜索功能添加通用约束:
func search<T: Baz>(searchText: String?, completion: @escaping ([T]?, Error?) -> ()) {
searchClient.search(T.index, searchText) { (json, error) in
guard error == nil else { completion(nil, error!) }
if let json = json {
completion(Baz.loadFromJSON(json: json), nil)
} else {
completion([], nil)
}
}
}