#ios #swift #generics
#iOS #swift #универсальные
Вопрос:
В настоящее время я изучаю, как реализовать универсальную функцию. Я пытаюсь создать функцию, которая будет возвращать обратный вызов с универсальным типом
Вот мой код
static func performPOST<T: DomainEntity>(action: Module, completion: @escaping (CallbackResponse, DomainObjectWrapper<T>?) -> Void) {
//logic implementation at first
switch action {
case .getMenuItem:
self.alamofireManager.request(urlRequest, encoding: URLEncoding.default, headers: headers).responseObject { (response: DataResponse<DomainObjectWrapper<MenuItemDO>>) in
var validateRequestResponse = RestHelper.validateRequestResponse(response: response)
let responseObject = validateRequestResponse.responseObject
if validateRequestResponse.isSuccess {}
else {
if let errorMessage = responseObject?.error {
validateRequestResponse.message = errorMessage
}
else if let warningMessage = responseObject?.warning {
validateRequestResponse.message = warningMessage
}
}
callbackResponse = RestHelper.bindValidateRequestResponse(validateRequestResponse: validateRequestResponse)
completion(callbackResponse, responseObject)
}
case .makeSales: break
case .attendance: break
}
}
Я получаю эту ошибку из Xcode. Это не позволит мне скомпилироваться.
completion(callbackResponse, responseObject) <<-- This Line
Cannot convert value of type 'DomainObjectWrapper<MenuItemDO>?' to expected argument type 'DomainObjectWrapper<_>?'
Вот мои другие классы
public class DomainObjectWrapper<T: Mappable>: Mappable {
public var data = [T]()
}
public class DomainEntity: Mappable {
public var id = UUID().uuidString
public var isDeleted = false
}
public class MenuItemDO: DomainEntity {
public var categoryId: String?
public var categoryName: String?
}
Кто-нибудь может подсказать мне, чего мне не хватает?
Спасибо
Комментарии:
1. Как вы вызываете этот метод? На какой строке вы получаете сообщение об ошибке? Можете ли вы дополнить вопрос этими деталями?
2. Как вы думаете, почему ваш метод должен быть универсальным?
3. Привет @Cristik, Xcode не будет компилировать код. Ошибка компилятора указана выше. Спасибо
4. @Sweeper, потому что будет много вызовов API, которые вернут DomainObjectWrapper<DifferentValue> . Итак, я думаю, что создание универсальной функции поможет мне избежать избыточного кода. Спасибо
Ответ №1:
потому что будет много вызовов API, которые вернут DomainObjectWrapper. Итак, я думаю, что создание универсальной функции поможет мне избежать избыточного кода. Спасибо
Если это так, то вы бы использовали DataResponse<DomainObjectWrapper<T>>
вместо DataResponse<DomainObjectWrapper<MenuItemDO>>
в параметре закрытия вызова Alamofire:
static func performPOST<T: DomainEntity>(action: Module, completion: @escaping (CallbackResponse, DomainObjectWrapper<T>?) -> Void) {
//logic implementation at first
switch action {
// this line
self.alamofireManager.request(urlRequest, encoding: URLEncoding.default, headers: headers).responseObject { (response: DataResponse<DomainObjectWrapper<T>>) in // <----- this line
var validateRequestResponse = RestHelper.validateRequestResponse(response: response)
let responseObject = validateRequestResponse.responseObject
if validateRequestResponse.isSuccess {}
else {
if let errorMessage = responseObject?.error {
validateRequestResponse.message = errorMessage
}
else if let warningMessage = responseObject?.warning {
validateRequestResponse.message = warningMessage
}
}
callbackResponse = RestHelper.bindValidateRequestResponse(validateRequestResponse: validateRequestResponse)
completion(callbackResponse, responseObject)
}
}
}
Комментарии:
1. Привет, подметальщик. Большое спасибо за ваш ответ. Я получаю ошибку в коде завершения (). В принципе, мой ResponseObject верен. Однако каким-то образом родительская функция обратного вызова не распознает мой блок завершения внутри корпуса switch (ResponseObject). Надеюсь, вы понимаете, что я имею в виду. Спасибо
2. @Alvin О, я только что понял! Почему у вас нет
switch
havecase
s? И какую ошибку вы получаете?3. Привет, на самом деле есть, я просто пытаюсь упростить свой код для объяснения здесь :). Ошибка — это та, которую я указал в своем вопросе :). Спасибо!
4. @Alvin Ты изменил
DataResponse<DomainObjectWrapper<MenuItemDO>>
наDataResponse<DomainObjectWrapper<T>>
, как я тебе сказал? Если это так, сообщение об ошибке не должно появляться. Или вы имеете в виду, что получаете сообщение об ошибке при вызовеperformPOST
?5. Я изменил его. Но я не смог получить свое свойство MenuItemDO. Я не смог получить данные из JSON. Я могу получить только свойство DomainEntity. Есть ли обходной путь для этого? Или моя функция неверна в начале? Я обновил структуру других моих классов. Пожалуйста, направьте меня. Спасибо
Ответ №2:
Недавно я создал подходящее решение для функций с общими параметрами. Вот пример шаблона командной строки. Таким образом, вы могли бы использовать этот шаблон, получая обратный вызов с универсальным параметром.
protocol ParameterCommand {
func execute(with parameter: Any)
}
protocol CallbackCommand: ParameterCommand {
associatedtype CallBackParameterType
func execute(with callback: @escaping (CallBackParameterType) -> Void)
}
extension CallbackCommand {
func execute(with parameter: Any) {
if let parameter = parameter as? (CallBackParameterType) -> Void {
execute(with: parameter)
}
}
}