#arrays #swift #dateformatter
#массивы #swift #dateformatter
Вопрос:
У меня есть кнопка, которая, когда пользователь нажимает на нее, сохраняет дату события в своем календаре, используя дату начала и дату окончания события.
Эта дата начала и дата окончания загружаются из ответа json, но обе даты получены в одной строке.
Формат, который я получаю для ответа, выглядит следующим образом:
{
"events":[
{
"date":"5/12/2021 - 5/14/2021",
},
{
"date":"6/22/2021 - 6/25/2021",
}
]
}
Чтобы правильно сохранить в календаре, мне нужно отделить начальную и конечную даты от строк, отформатированных следующим образом: «ММ / ДД / ГГГГ — ММ / ДД / ГГГГ», чтобы первая дата в строке была переменной с именем StartDate, а вторая дата — переменной с именем EndDate .
Я могу проанализировать ответ json, и кнопка работает нормально, если я жестко запрограммирую два «фиктивных» массива, но как мне разделить ответ на две отдельные переменные даты, как только я получу это «ММ / ДД / ГГГГ — ММ / ДД / ГГГГ»?
Комментарии:
1. Реализуйте
init(from decoder : Decoder)
и добавьте логику для разделенияString
на двеDate
2. Я могу проанализировать ответ json, но как мне разделить дату, как только я получу это «ММ / ДД / ГГГГ — ММ / ДД / ГГГГ»?
3. Вы не можете с помощью DateFormatter, у вас есть две даты, поэтому вам нужно сначала разделить строку на 2 строки, представляющие 2 даты, а затем для каждой использовать
DateFormatter
Ответ №1:
Это должно сработать для вас:
struct Response: Codable {
let events: [Event]
}
struct Event: Codable {
let date: String
let startDate: Date
let endDate: Date
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
date = try container.decode(String.self, forKey: .date)
let splitted = date.components(separatedBy: " - ")
guard let startDateString = splitted.first,
let endDateString = splitted.last else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "'date' should follow the format 'DATE1 - DATE2'"))
}
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "M/dd/yyyy"
guard let extractedStartDate = formatter.date(from: startDateString),
let extractedEndDate = formatter.date(from: endDateString) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The provided dates are not in the correct format M/dd/yyyy"))
}
startDate = extractedStartDate
endDate = extractedEndDate
}
}
И пример синтаксического анализа из вашего json:
let json = """
{
"events":[
{
"date":"5/12/2021 - 5/14/2021",
},
{
"date":"6/22/2021 - 6/25/2021",
}
]
}
"""
let response = try JSONDecoder().decode(Response.self, from: json.data(using: .utf8)!)
print(response.events)
Комментарии:
1. Я думаю, было бы разумнее сделать свойства даты необязательными, чем принудительно разворачивать столько раз
2. Поскольку событие не имело бы смысла без дат и инициализации (декодера), я предпочел сделать его аварийным с принудительным развертыванием
3. Если сделать их необязательными, вызывающему коду придется решать, что делать, когда дата равна нулю, «сделать ее аварийной» — действительно плохая привычка.
4. Лучше выбросить DecodingError
5. Хорошо, я редактирую это прямо сейчас, я думаю, вы всегда чему-то учитесь