Основная проблема здесь заключается в том, что типом, который вы хотите, является Void, но Void не может быть декодируемым, и вы не можете сделать его декодируемым, потому что неноминальные типы (такие как Void) не могут быть расширены.Это всего лишь текущее ограничение Swift.
Правильным решением этой проблемы является перегрузка.Создайте два метода:
// For values
func request<D: Decodable>(from urlString: String,
useToken: Bool = false,
requestType: RequestType = .get,
body: Data? = nil,
expecting type: D.Type,
completion: @escaping (Result<D>) -> Void) {}
// For non-values
func request(from urlString: String,
useToken: Bool = false,
requestType: RequestType = .get,
body: Data? = nil,
completion: @escaping (Error?) -> Void) {}
Создайте еще один общий метод, который превращает запрос в данные и который оба могут вызывать:
func requestData(from urlString: String,
useToken: Bool = false,
requestType: RequestType = .get,
body: Data? = nil,
completion: @escaping (Result<Data>) -> Void) {}
Ваша функция запроса декодирования теперь преобразует .success(Data)
вD
.Ваша функция запроса без декодирования отбрасывает данные (или, возможно, гарантирует, что они пусты, если вы педантичны по этому поводу), и вызывает обработчик завершения.
Если вы хотите, чтобы ваш код был немного большепараллельно, так что он всегда передает результат, а не ошибку ?, тогда вы все равно можете получить это с подстройкой к сигнатуре:
func request(from urlString: String,
useToken: Bool = false,
requestType: RequestType = .get,
body: Data? = nil,
completion: @escaping (Result<Void>) -> Void) {}
Но перегрузка по-прежнему здесь ответ.
(СТАРЫЕ ОТВЕТЫ) Здесь нет проблем с передачей nil
, если D
можно каким-то образом вывести.Но должен быть способ сделать вывод D
.Например, следующее должно быть хорошо:
request(from: "") { (result: Result<Bool?>) in
print(result)
}
Что не будет хорошо, так это:
request(from: "") { (result) in
print(result)
}
Потому что в этом случае нет способа определить, что D
is.
Тем не менее, учитывая вашу цель, вы не хотите, чтобы Type
был необязательным в любом случае.Как вы говорите, иногда результат «ничего не возвращает».Правильный тип для «ничего не возвращает» - Void
, а не ноль.
func request<D: Decodable>(from urlString: String,
useToken: Bool = false,
body: Data? = nil,
expecting type: D.Type = Void.self, // <<----
completion: @escaping (Result<D>) -> Void)
(я предполагаю, что тогда вы хотите Result<D>
вместо Result<D?>
, но любой из них может быть правильным в зависимости от вашеготочный вариант использования.)
Void
- это обычный тип в Swift.Это тип с ровно одним значением: ()
, пустой кортеж.