Я пытаюсь провести рефакторинг нескольких общих методов в моем классе Repository
, который создает закрытие завершения для вызова API.Основное изменение, которого я хочу добиться, - реализовать новый тип Swift 5 Result
и немного обобщить завершение.
Предыдущая (и рабочая версия) выглядит следующим образом:
private func getAllCompletion<T>(_ type: T.Type, completion: (() -> Void)?) throws -> ((GetResourceRequest<T>) -> Void) where T: Codable{
switch type {
case is Acronym.Type:
return getCompletion(for: \Repository.acronyms, completion: completion) as! ((GetResourceRequest<T>) -> Void)
case is User.Type:
return getCompletion(for: \Repository.users, completion: completion) as! ((GetResourceRequest<T>) -> Void)
case is Category.Type:
return getCompletion(for: \Repository.categories, completion: completion) as! ((GetResourceRequest<T>) -> Void)
default:
throw ErrorFactory.invalidType(type).error
}
}
private func getCompletion<T>(for keyPath: ReferenceWritableKeyPath<Repository, [T]>, completion: (() -> Void)?) -> ((GetResourceRequest<T>) -> Void) {
return {[weak self] resourceRequest in
switch resourceRequest {
case .success(let resource):
self?[keyPath: keyPath] = resource
case .failure:
break
}
completion?()
}
}
Я произвел рефакторинг и попытался обобщить его немного таким образом:
private func getCompletion<ResourceType>(_ type: ResourceType.Type, completion: ((Error) -> Void)?) -> ((Result<ResourceType, Error>) -> Void) where ResourceType: Codable{
switch type {
case is [Acronym].Type:
getCompletion(for: \Repository.acronyms, with: completion)
case is [User].Type:
getCompletion(for: \Repository.users, with: completion)
case is [Category].Type:
getCompletion(for: \Repository.categories, with: completion)
default:
let error = ErrorFactory.invalidType(type).error
completion?(error)
}
}
private func getCompletion<ResourceType>(for keyPath: ReferenceWritableKeyPath<Repository, ResourceType>, with completion: ((Error?) -> Void)?) -> ((Result<ResourceType, Error>) -> Void) {
return { [weak self] result in
switch result {
case .success(let resource):
self?[keyPath: keyPath] = resource
completion?(nil)
case .failure(let error):
completion?(error)
}
}
}
Iне могу понять, что мне не хватает, но это не скомпилируется.Сообщение, которое я получаю для всех трех вызовов getCompletion(for:completion)
, выглядит следующим образом:
Cannot convert value of type 'ReferenceWritableKeyPath<Repository, [Acronym]>' to expected argument type 'ReferenceWritableKeyPath<Repository, _>'
Заранее благодарю за ответы и извиняюсь, если мне не хватает чего-то действительно очевидного.
Я также знаю, что было бы намного лучше использовать решение на основе Rx
вместо дополнений, но для этого конкретного примера я не хотел использовать сторонние библиотеки, потому что хотел посмотреть, могу ли я управлятьбез них:).