我有通用的方法来创建扩展协议FromResponse
的对象。
extension FromResponse {
static func object<T>(_ response: [String: Any]?) -> T? where T: FromResponse, T: NSObject {
guard let response = response else { return nil }
let obj: T = T()
return obj
}
}
所以每当我想从代码中的任何地方调用它时都没有问题。让我们说:
let myObject: MyObject? = MyObject.object(response)
工作完美。但有时我会从我的回复中获取对象数组,所以我也想要通用解析器:
static func objects<T>(_ response: [[String: Any]]?) -> [T]? where T: FromResponse, T: NSObject {
guard let response = response else { return nil }
var returnArray: [T] = [T]()
for singleResponse in response {
if let object: T = T.object(singleResponse) {
returnArray.append(object)
}
}
return returnArray
}
所以我期望从这个方法返回MyObject
的数组,但实际上我在调用它时遇到了编译错误:
let myObjects: [MyObject]? = MyObject.objects(response)
它说:
通用参数&#39; T&#39;无法推断
嗯,我知道这是什么意思但我确实指定了类型,所以这个错误不应该发生。当我这样做时:
var typ: [MyObject] = [MyObject]()
for singleResponse in (response as? [[String: Any]])! {
let pack: MyObject? = MyObject.object(singleResponse)
typ.append(pack!)
}
有效!
为什么呢?如何使用返回泛型对象数组的解析器?
答案 0 :(得分:2)
我不确定为什么Swift说“通用参数&#39; T&#39;无法推断“,但我的猜测是它与数组协方差有关。
什么是协方差?考虑一下:
class Base { }
class Sub: Base { }
func f(_ array: [Base]) { }
您可以将[Sub]
传递给f
吗?在Swift中,你可以。由于Sub
是Base
的子类型,[Sub]
是[Base]
的子类型。 (这称为“协方差”。)因此,您可以在允许[Sub]
的任何地方传递[Base]
:
f([Sub]())
// No errors.
您可以返回[Sub]
,其中[Base]
是预期的:
func g() -> [Base] { return [Sub]() }
// No errors.
您可以将[Sub]
分配给[Base]
变量:
let bases: [Base] = [Sub]()
// No errors.
回到你的代码:
static func objects<T>(_ response: [[String: Any]]?) -> [T]? ...
let myObjects: [MyObject]? = MyObject.objects(response)
当然MyObject.objects(_:)
必须返回一个可以视为[MyObject]?
的类型。但是[MyObject]?
的任何子类型也是可以接受的。类型没有严格约束。我想这就是斯威夫特不喜欢它的原因。
解决方法是使用您在Swift标准库中的许多地方看到的模式,明确告诉Swift您想要什么类型:
static func objects<T>(ofType type: T.Type, from response: [[String: Any]]?) -> [T]? ...
// Note that you might not actually have to use the `type` parameter
// in the method definition.
let myObjects = MyObject.objects(ofType: MyObject.self, from: response)
目前尚不清楚为什么这种方法完全在MyObject
类。也许你应该在[[String: Any]]
:
extension Collection where Element == [String: Any] {
func objects<T>(ofType type: T.Type) -> [T]? ...
}
let myObjects = response.objects(ofType: MyObject.self)