我正在使用此扩展程序来检索urlSession回调中的HTTP标头:
extension HTTPURLResponse {
func get(_ header: String) -> String? {
let keyValues = allHeaderFields.map { (String(describing: $0.key).lowercased(), String(describing: $0.value)) }
if let headerValue = keyValues.filter({ $0.0 == header.lowercased() }).first {
return headerValue.1
}
return nil
}
}
这很好用,我可以像这样检索标题元素:
if let metaInt = httpResponse.get("icy-metaint") {
self.icyMetaInt = Int(metaInt)
}
现在我想通过引入一个通用函数来使它变得更优雅:
func getHeader<T>(_ httpResponse: HTTPURLResponse, _ headerName: String) -> T? {
guard let element = httpResponse.get(headerName) else {
return nil
}
return T(element)
}
目的是使用这样的陈述:
self.icyMetaInt = getHeader(httpResponse, "icy-metaint")
我相信像C#这样的东西会起作用。但Swift编译器抱怨道:
非名义类型&#39; T&#39;不支持显式初始化
代表
return T(element)
即使我使用
return T.init(element)
有没有机会实现我的想法?
编辑:添加T? (编辑时一定丢失了)答案 0 :(得分:0)
这是因为编译器不知道它应该调用哪个初始化器,因为你正在做的事情太过笼统,就像错误所说的那样。 你想要实现的目标是什么,但实施取决于你所取得的成就。
简而言之,如果您希望能够初始化许多不同的类型,无论是原语还是对象,您应该定义一个新协议,扩展每个类型以实现您认为合适的协议并限制T类型这个协议。
protocol HTTPHeaderProtocol {
init(_ headerProtocolString: String?)
}
class MyCustomObject: HTTPHeaderProtocol {
var myString = ""
required init(_ headerProtocolString: String?) {
self.myString = headerProtocolString ?? ""
}
}
extension String: HTTPHeaderProtocol {
init(_ headerProtocolString: String?) {
self.init(headerProtocolString)
}
}
extension Int: HTTPHeaderProtocol {
init(_ headerProtocolString: String?) {
self.init(headerProtocolString)
}
}
extension HTTPURLResponse {
func get(_ header: String) -> String? {
let keyValues = allHeaderFields.map { (String(describing: $0.key).lowercased(), String(describing: $0.value)) }
if let headerValue = keyValues.filter({ $0.0 == header.lowercased() }).first {
return headerValue.1
}
return nil
}
func getHeader<T:HTTPHeaderProtocol>(_ httpResponse: HTTPURLResponse, _ headerName: String) -> T? {
guard let element = httpResponse.get(headerName) else {
return nil
}
return T(element)
}
}
这将有效,希望有所帮助:)