#swift #swiftui #decodable
#swift #swiftui #декодируемый
Вопрос:
Заранее спасибо за помощь.
Я впервые работаю над вызовом API в SwiftUI. Я вернул часть данных, используя structs / decodable . И я использую перечисления для доступа к каждому слою. Однако API, который я использую, использует текущую дату в качестве ключа, и я изо всех сил пытаюсь получить доступ к этому слою данных без использования строкового литерала. Есть идеи?
Вот что у меня есть.
struct NEObjects: Decodable {
let fromToday: [NEObject]
enum CodingKeys: String, CodingKey {
case fromToday = "2021-02-16"
}
}
У меня есть текущая дата, сохраненная в пользовательских настройках по умолчанию. Но если я сделаю что-то вроде
let date = UserDefaults.standard.string(forKey: "current_date")
case fromToday = date
Затем я получаю сообщение об ошибке «Необработанное значение для enum case должно быть литералом»
Я не уверен, как еще я могу получить доступ к этому слою, потому что я новичок в SwiftUI.
Вот полная модель данных для справки:
import Foundation
let date = UserDefaults.standard.string(forKey: "current_date")
struct NEOData: Decodable {
let elementCount: Int
let neObjects: NEObjects
enum CodingKeys: String, CodingKey {
case elementCount = "element_count"
case neObjects = "near_earth_objects"
}
}
struct NEObjects: Decodable {
let fromToday: [NEObject]
enum CodingKeys: String, CodingKey {
case fromToday = "2021-02-15"
}
}
struct NEObject: Decodable {
let name: String
let absoluteMagnitude: Double
let diameter: Diameter
let isHazardous: Bool
let closeApproachData: [CloseApproachData]
let isSentry: Bool
enum CodingKeys: String, CodingKey {
case name = "name"
case absoluteMagnitude = "absolute_magnitude_h"
case diameter = "estimated_diameter"
case isHazardous = "is_potentially_hazardous_asteroid"
case closeApproachData = "close_approach_data"
case isSentry = "is_sentry_object"
}
}
struct Diameter: Decodable {
let kilometers: Kilometers
let meters: Meters
let miles: Miles
let feet: Feet
}
struct CloseApproachData: Decodable {
let velocity: Velocity
let missDistance: MissDistance
let date: String
enum CodingKeys: String, CodingKey {
case velocity = "relative_velocity"
case missDistance = "miss_distance"
case date = "close_approach_date"
}
}
struct Velocity: Decodable {
let mph: String
let kph: String
enum CodingKeys: String, CodingKey {
case mph = "miles_per_hour"
case kph = "kilometers_per_hour"
}
}
struct MissDistance: Decodable {
let kilometers: String
let miles: String
}
struct Kilometers: Decodable {
let min: Double
let max: Double
enum CodingKeys: String, CodingKey {
case min = "estimated_diameter_min"
case max = "estimated_diameter_max"
}
}
struct Meters: Decodable {
let min: Double
let max: Double
enum CodingKeys: String, CodingKey {
case min = "estimated_diameter_min"
case max = "estimated_diameter_max"
}
}
struct Miles: Decodable {
let min: Double
let max: Double
enum CodingKeys: String, CodingKey {
case min = "estimated_diameter_min"
case max = "estimated_diameter_max"
}
}
struct Feet: Decodable {
let min: Double
let max: Double
enum CodingKeys: String, CodingKey {
case min = "estimated_diameter_min"
case max = "estimated_diameter_max"
}
}
Комментарии:
1. Почему бы не использовать словарь, [Строка: НЕОбъект]?
Ответ №1:
Не видя JSON, я просто предполагаю, что вы хотите, чтобы ваша NEObjects
структура выглядела так:
struct NEObjects: Decodable {
let objectsByDay : [String : NEObject]
}
Это будет декодировать JSON, который выглядит следующим образом:
{
"2021-02-16" : [
{ ... a bunch of your custom objects ... }
]
}
Комментарии:
1. Спасибо! Я не знал, что могу это сделать. Сейчас у меня возникли проблемы с инициализацией значения по умолчанию для состояния. Не могли бы вы объяснить это и для меня? У меня есть это:
@State var results = NEOData(elementCount: 0, neObjects: [NEObjects])
но я получаю сообщение об ошибке «Невозможно преобразовать значение типа ‘[NEObjects]. Введите » ожидаемый тип аргумента «NEOBjects»»
Ответ №2:
Конечный результат: у меня был ненужный дополнительный слой. После реализации предложения Джона.
Модель
import Foundation
struct NEOData: Decodable {
let elementCount: Int
let neObjects: [String : [NEObject]]
enum CodingKeys: String, CodingKey {
case elementCount = "element_count"
case neObjects = "near_earth_objects"
}
}
struct NEObject: Decodable {
let name: String
let absoluteMagnitude: Double
let diameter: Diameter
let isHazardous: Bool
let closeApproachData: [CloseApproachData]
let isSentry: Bool
enum CodingKeys: String, CodingKey {
case name = "name"
case absoluteMagnitude = "absolute_magnitude_h"
case diameter = "estimated_diameter"
case isHazardous = "is_potentially_hazardous_asteroid"
case closeApproachData = "close_approach_data"
case isSentry = "is_sentry_object"
}
}
struct Diameter: Decodable {
let kilometers: Kilometers
let meters: Meters
let miles: Miles
let feet: Feet
}
struct CloseApproachData: Decodable {
let velocity: Velocity
let missDistance: MissDistance
let date: String
enum CodingKeys: String, CodingKey {
case velocity = "relative_velocity"
case missDistance = "miss_distance"
case date = "close_approach_date"
}
}
struct Velocity: Decodable {
let mph: String
let kph: String
enum CodingKeys: String, CodingKey {
case mph = "miles_per_hour"
case kph = "kilometers_per_hour"
}
}
struct MissDistance: Decodable {
let kilometers: String
let miles: String
}
struct Kilometers: Decodable {
let min: Double
let max: Double
enum CodingKeys: String, CodingKey {
case min = "estimated_diameter_min"
case max = "estimated_diameter_max"
}
}
struct Meters: Decodable {
let min: Double
let max: Double
enum CodingKeys: String, CodingKey {
case min = "estimated_diameter_min"
case max = "estimated_diameter_max"
}
}
struct Miles: Decodable {
let min: Double
let max: Double
enum CodingKeys: String, CodingKey {
case min = "estimated_diameter_min"
case max = "estimated_diameter_max"
}
}
struct Feet: Decodable {
let min: Double
let max: Double
enum CodingKeys: String, CodingKey {
case min = "estimated_diameter_min"
case max = "estimated_diameter_max"
}
}