我有以下Swift通用方法:
static func getRecords<T>(_ which: Which, from table: Table, completionHandler: @escaping ([T]) -> Void)
{
let url: String = DatabaseInterface.getUrl(which, from: table)
Http.get(url: url)
{
response, error in
if nil != error
{
print("get\(table.rawValue)() failed; error = \(error!)")
return
}
var objects: [T] = []
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd" // Matches PHP's "Y-m-d" \Date format.
let records = (response!["records"])!
for record in (records as! [NSDictionary])
{
// This line fails with the error
// 'T' cannot be constructed because it has no accessible initializers
objects.append(T(fromDictionary: record as! [String: Any]))
}
DispatchQueue.main.async
{
completionHandler(objects)
}
}
}
Http.get()方法从服务器检索记录并将JSON解码为字典数组。
objects.append()行因此错误而失败:
'T'无法构造,因为它没有可访问的初始值设定项
我的第一个问题:是否可以在泛型函数中创建由类型占位符指定的类型的新实例?
我的第二个问题:如果有可能,这样做的正确语法是什么?
答案 0 :(得分:0)
编译器不知道T有一个初始化器。您需要将其约束为包含init(fromDictionary:)
的协议或类protocol JSONInitializable {
init(fromDictionary: [String: Any])
}
static func getRecords<T: JSONInitializable>(
_ which: Which,
from table: Table,
completionHandler: @escaping ([T]) -> Void
) {
let url = DatabaseInterface.getUrl(which, from: table)
Http.get(url: url) { _response, error in
guard let response = _response as? [String: [[String: Any]]],
error == nil else {
print("get\(table.rawValue)() failed; error = \(error!)")
return
}
guard let objects = response["records"]?.map(T.init(fromDictionary:)) {
fatalError("`response` doesn't have a value for the key \"records\".")
}
DispatchQueue.main.async { completionHandler(objects) }
}