ошибка вывода типа в обратном вызове - PullRequest
0 голосов
/ 31 мая 2018

У меня ошибка вывода типа, которую я не могу устранить.Я приложил самый важный фрагмент ниже.Процесс синтаксического анализа выполняется отдельно Decoder в APIClient.

. Почему APIClient execute не распознает T как [Chapter] каклиния completion(Result.success(decodedData)) имеет этот тип?

enter image description here

func loadFeed(completion: @escaping (Result<[Chapter]>) -> Void) {
    APIClient.shared.execute(APIRequest.loadFeed) { response in

        guard let decodedData = response.decodedData else { return }
        completion(Result.success(decodedData))
    }
}

Вышеприведенный фрагмент - это то, как я называю APIClient в моем классе Services.

class APIClient: APIClientProtocol {
    static let shared = APIClient()
    func execute<T: Decodable>(_ apiRequest: APIRequestDefining,
                               responseDecoder: ResponseDecoder = .jsonDecoding,
                               completionHandler: @escaping (Response<T>) -> Void) {
        var response = Response<T>(request: request, httpResponse: dataResponse.response, data: dataResponse.data)

        do {
            try responseDecoder.decode(response: &response)
        } catch {
            response.error = error
        }

        completionHandler(response)
    }
}



public struct Response<T> {
    var decodedData: T?
}



enum Result<Value> {
    case success(Value)
    case failure(Error)
}

РЕДАКТИРОВАТЬ: Для пояснения ниже приведен фрагмент кода, где и как я decode необработанный ответ на предполагаемый объект.

struct JSONResponseDecoder: ResponseDecoding {
    func decode<T: Decodable>(response: inout Response<T>) throws {
        guard let data = response.data else { return }
        do {
            try response.decodedData = JSONDecoder().decode(T.self, from: data)
        } catch {
            throw(ApplicationError(errorType: .decodingError))
        }
    }
}

РЕДАКТИРОВАТЬ !!!!:

Я нашел действительно странную вещь, я удаляю строку с guard, все отлично работает, почему это так?

До : enter image description here После : enter image description here

Ответы [ 3 ]

0 голосов
/ 31 мая 2018

Вы сказали: «Выполнение не признает, что Т - это [Глава]», и мне интересно, почему вы ожидаете этого.

У вас есть функция loadFeed с блоком завершения, который использует универсальный тип Chapter.

Затем у вас есть метод execute с универсальным типом T. Когда вы вызываете ваш метод execute, он ничего не знает о типе Chapter.

Пример, где я получаю ту же ошибку, что и вы:

 func execute<T>(completionHandler: @escaping (T) -> Void) {

 }
 self.execute { (result) in
 }

Решение состоит в том, чтобы привести параметр так, чтобы T мог быть выведен.В твоем случае:

func execute<T>(completionHandler: @escaping (T) -> Void) {

 }
 self.execute { (result:[Chapter]) in
 }

Обобщения потрясающие:)

0 голосов
/ 03 июня 2018

Я нашел ответ в другом сообщении.

Причина ошибки в том, что компилятор ссылается на тип возвращаемого значения замыкания, только когда в замыкании есть один оператор.

https://forums.swift.org/t/problems-with-closure-type-inference/11859/2

0 голосов
/ 31 мая 2018

Ваш completionHandler принимает параметр с универсальным типом, так что будьте явным с вашим типом в замыкании, иначе он не сможет вывести тип:

func loadFeed(completion: @escaping (Result<[Chapter]>) -> Void) {
    APIClient.shared.execute(APIRequest.loadFeed) { (chapters: [Chapter]) -> () in

        guard let decodedData = chapters.decodedData else { return }
        completion(Result.success(decodedData))
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...