2

我有以下结构和功能。

struct ApiResponse<TResponse: Codable>: Codable {
    var isSuccess: Bool
    var mainResponse: TResponse?
}

public struct SomeResponse: Codable {
    var someProperty: String
}

public func postAsync<TRequest: Codable, TResponse: Codable>(route: String, request: TRequest) async throws -> TResponse? {

    let body = try JsonEncoder().encode(request)
    let urlRequest = createUrlRequest(route: route, method: "POST", body: body)

    let (data, _) = try await URLSession.shared.data(for: urlRequest)
    let apiResponse = try JsonDecoder().decode(ApiResponse<TResponse>.self, from: data)
    return response.mainResponse
}

我想这样调用postAsyncfunc 但它说**Generic parameter 'TResponse' could not be inferred**我如何调用这个方法?我尝试了不同的方法但没有解决。

 - let res = await postAsync(route: "MyController/Get", request: someRequest) as? SomeResponse
 - let res: SomeResponse = await postAsync(route: "MyController/Get", request: someRequest)
4

2 回答 2

3

您的函数不返回SomeResponse,而是返回SomeResponse?,所以您的意思是:

let res = ... as SomeResponse? // Note `as`, not `as?`

或者

let res: SomeResponse? = ...

我同意 EmilioPaleaz 关于如何改进 API 的观点,但我建议添加一个默认值,这样可以两全其美:

... request: TRequest, returning: TResponse.Type = TResponse.self) async throws -> ...

这样,当返回类型已知时,您可以省略它。

于 2021-06-22T15:40:04.670 回答
2

我不确定为什么您尝试的解决方案失败了,也许它们不适用于 async/await 功能。

也就是说,虽然通常可以使用隐式泛型,但 Swift 中更常见的做法是将类型作为参数之一包含在内,而不是保持隐式。这就是它在像JSONDecoder.

我建议将您的函数签名更改为:

public func postAsync<TRequest: Codable, TResponse: Codable>(route: String, request: TRequest, receive: TResponse.Type) async throws -> TResponse? {

并这样称呼它:

let res = await postAsync(route: "MyController/Get", request: someRequest, receive: SomeResponse.self)
于 2021-06-22T15:35:39.013 回答