Как создать структуру Dynami c с необязательным типом generi c - PullRequest
0 голосов
/ 29 января 2020

Я создал декодируемую базовую структуру для ответа API.

struct ResponseBaseModel<T: Decodable>: Decodable {
    let status: Bool
    let message: String
    var result: T?

    private enum CodingKeys: String, CodingKey {
        case result, message, success,status,statusCode
    }

     init(from decoder: Decoder) throws {
           let values = try decoder.container(keyedBy: CodingKeys.self)
            if let result = try? values.decode(T.self, forKey: .result) {
                self.result = result
            }
        status = try  values.decode(Bool.self, forKey: .status)
        message = try  values.decode(String.self, forKey: .message)
       }
}

// вот ответ API

{
    "status": true,
    "statusCode": 200,
    "message": "Theater list successfully",
    "result": [
        {
            "id": 1,
            "name": "Galaxy",
            "picture": "https://ctdemo.workpc.online/kshatrainfotech/abol-app/public/storage/images/theaters/default.png",
            "is_notify": false
        }
    ]
}

вот как я использую его для вызова API

 apimanager.fetch { [weak self] (response: Result<ResponseBaseModel<[Theater]>, ApiError>) in
        self?.handelResponse(response: response) { response in
            switch response {
            case .success(let theaterList):
                self?.theaterViewModels = theaterList.map{ TheaterViewModel(theaterModel: $0)}
                self?.responseHandler(.success(self!.theaterViewModels))
            case .failure(let apiError):
                self?.responseHandler(.failure(apiError))
            }
        }
    }

, но у некоторых API нет результата, например

{"status": true, "statusCode": 200, "message": "api.DATA_UPDATED_SUCCESS"}

как обрабатывать вышеуказанный ответ с моделью ResponseBaseModel. Потому что мне приходится передавать любой тип при работе со структурой ResponseBaseModel.

ResponseBaseModel<?>

Я уже пробовал ResponseBaseModel<nil>, но это не сработало.

1 Ответ

0 голосов
/ 29 января 2020

Я пытаюсь немного ответить на ваш вопрос, чтобы показать, почему то, что вы хотите, невозможно таким образом. Подумайте о следующей структуре:

struct TestStruct<T> {
    let code:Int
    var value:T?

    init(code:Int) {
        self.code = code
    }
} 

Обычно вы используете ее следующим образом:

var s = TestStruct<String>(code:42)
s.value = "abc"

print (s) // TestStruct<String>(code: 42, value: Optional("abc"))

Теперь вы говорите: «О, мне нужен TestStruct только для некоторого кода, без value at all "и попробуйте следующее:

var codeOnly = TestStruct<nil>(code:42)
print (codeOnly)

Компилятор жалуется, потому что ему нужен выделенный тип для свойства value. Почему это не работает? Потому что подумайте о следующем утверждении:

let v = codeOnly.value
// or
codeOnly.value = "String"

Здесь компилятору необходимо знать, к какому типу относится свойство codeOnly.value. Поскольку он не может сейчас, он не допустит нетипизированный TestStruct.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...