在我的应用程序中,几个控制器具有非常相似的代码结构,差异非常小,因此为了优化,我决定为这些控制器创建一个基础,并从基础继承每个特定的控制器。
我有一个发送网络请求和处理响应的函数,我将响应结构作为参数传递给这个函数,以便该函数返回一个现成的响应结构给我。每个这样的结构都是Decodable。
这样的结构的一个例子:
struct APIAnswerUserActivity: Decodable {
let status: String
let code: Int?
let data: [UserActivity]?
let total: Int?
}函数对于网络请求,接受Decodable.Protocol类型的对象(结构)作为jsonType参数:
public func networkRequest<T: Decodable> (
url: String,
timeout: Double = 30,
method: URLMethods = .GET,
data: [String : String]? = nil,
files: [URL]? = nil,
jsonType: T.Type,
success: @escaping (T) -> Void,
failure: @escaping (APIError) -> Void
) -> URLSessionDataTask { ... }主控制器中有几个参数,我在子控制器中通过override重写了这些参数,其中一个参数应该是Decodable类型的对象,以便通用函数正确接收数据。响应的JSON结构非常相似,但仍然略有不同,无法为它们创建通用结构,因为数据仍然略有不同。
如果在主控制器中执行以下操作:
public var decodableType: Decodable.Type {
return APIAnswerUserActivity.self
}这是可行的,并且可以重新定义类型,但是网络函数不接受这一点,它需要Decodable.Protocol对象。如果为变量decodableType指定了decodable.Protocol类型,那么就不能再添加APIAnswerUserActivity.self,在调用networkRequest函数时,它会被悄悄接受。
在这种情况下该如何应对?我希望我能够正确和清楚地陈述我的问题的本质。谢谢!
发布于 2020-01-13 14:48:17
@ВладиславАртемьев,我仍然不确定我是否完全理解这个问题,因为你还没有分享接受Decodable类的代码。但问题似乎是关于如何传递Decodable类。
我希望下面的内容可以帮助你阐明如何在泛型上施加正确的约束,以及应该如何声明变量。你可以把它粘贴到操场上进行实验。
import Foundation
struct FakeToDo: Decodable {
var userId: Int
var id: Int
var title: String
var completed: Bool
}
enum URLMethods {
case GET
case POST
}
func networkRequest<T: Decodable> (
url: String,
timeout: Double = 30,
method: URLMethods = .GET,
data: [String : String]? = nil,
files: [URL]? = nil,
jsonType: T.Type,
success: @escaping (T) -> Void,
failure: @escaping (Error) -> Void
) -> URLSessionDataTask {
let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { (data, response, error) in
if error != nil {
failure(error!)
return
}
guard let data = data else { return }
let decoder = JSONDecoder()
guard let value = try? decoder.decode(T.self, from: data) else { return }
// get back on the main queue for UI
DispatchQueue.main.async {
success(value)
}
})
return task
}
class Example<T> where T: Decodable {
let type: T.Type
init(_ type: T.Type) {
self.type = type
}
public var decodableType: T.Type {
return type
}
}
let decodableType = Example(FakeToDo.self).decodableType
let url = "https://jsonplaceholder.typicode.com/todos/1"
let task = networkRequest(url: url, jsonType: decodableType,
success: { value in print(value) },
failure: { error in print(error) })
task.resume()https://stackoverflow.com/questions/59700351
复制相似问题