Вот JSON, который мне нужно декодировать, его изображение доступно по ссылке ниже, а также текст (форматирование не сработает, поэтому выглядит уродливо). Я почти уверен, что правильно представил его со своими структурами.
{
"успех": {
"всего": 1
},
"содержание": {
"цитаты": [
{
"цитата": "В прошлый раз не существует. Это только в этот раз. И в этот раз все будет иначе. Там только сейчас".,
«автор»: «Билл Мюррей»,
«длина»: «118»,
"теги": [
«Вдохновлять»,
"подарок"
],
"категория": "вдохновлять",
"title": "Вдохновляющая цитата дня",
«дата»: «2019-01-16»,
"id": null
}
],
"copyright": "2017-19 theysaidso.com"
}
}
Всякий раз, когда я запускаю свой код, который пытается взять поля из JSON и сохранить их в переменных, чтобы отобразить их в UITableView, происходит сбой. Я проверяю это, пытаясь сделать ярлык таким же, как имя автора в качестве заголовка.
«автор» - это поле в JSON.
Это важные части кода:
Class ViewController: UITableViewController {
...
var quoteArray = [Quote]()
//quoteArray Stores the quote objects that contain the fields I need
.....
//STRUCTS TO REPRESENT THE JSON
struct Quote: Decodable {
let quote: String?
let author: String?
let length: String?
let tags: [String]?
let category: String?
let title: String?
let date: String?
}
struct WebsiteObjectStruct: Decodable {
let success: SuccessStruct
let contents: ContentsStruct
}
struct SuccessStruct: Decodable{
let total: Int?
}
struct ContentsStruct: Decodable{
let quotes: [Quote]?
let copyright: String?
}
.....
// ФУНКЦИЯ, ГДЕ ДЕКОДИРУЕТСЯ
fileprivate func fetchJSON(){
...
self.websiteObject = try decoder.decode(WebsiteObjectStruct.self, from: data)
self.tableView.reloadData()
...
}
...
// Ячейка для строки в функции для таблицы
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellId")
let authorText = quoteArray[0].author
cell.textLabel?.text = author.text
//For quoteArray we are looking at zero index because in my JSON there
// is ONLY EVER ONE element, located at index 0, in quoteArray
return cell
}
}
Приложение запускается, а tableView пуст, у него нет имени автора (в данном случае Билла Мюррея). В любом случае, вот сообщение об ошибке:
Не удалось декодировать: typeMismatch (Swift.Array,
Swift.DecodingError.Context (codingPath: [], debugDescription:
Msgstr "Предполагается декодировать массив, но вместо этого нашел словарь.",
ringError: nil))
Он говорит, что ожидал декодировать массив, но вместо этого нашел словарь. Ну, я изменил его один раз, чтобы декодировать не массив, а структуру, и объявил переменную
в классе, который имел тип struct (назначение структуры отражает назначение массива).
Короче говоря, я немного изменил код, чтобы приспособить его к структуре, и он мог бы печатать имя автора ТОЛЬКО на консоли, если оператор печати находился в тех же скобках кодирования, что и оператор декодирования. Тем не менее, он не мог сохранить его в переменной для использования.
Я не думаю, что проблема в массиве по сравнению со словарем , но с "basicError" консоль говорит о том, что массив равен nil . Независимо от типа переменной, будь то массив или структура, переменная, помещаемая в textField, всегда равна нулю.
Я получаю эту ошибку:
Неустранимая ошибка: неожиданно найдено ноль при развертывании необязательного значения
Возможно, проблема с многопоточностью или асинхронностью?
Обновление: этот код работает:
class MainNetworkManager {
// Запросить формат JSON из wep API
static func fetchJSON(fetchUrl: String, quoteViewController: QuoteViewController) {
let urlString = fetchUrl
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, _, err) in
DispatchQueue.main.async {
if let err = err {
print("Failed to get data from url:", err)
return
}
guard let data = data else { return }
do {
// link in description for video on JSONDecoder
let decoder = JSONDecoder()
// Swift 4.1
decoder.keyDecodingStrategy = .convertFromSnakeCase
//self.webStruct = try decoder.decode(WebsiteObjectStruct.self, from: data)
// self?.quoteArray = quotesArray
// self?.reloadInputViews()
let tempStruct = try decoder.decode(WebsiteObjectStruct.self, from: data)
//print(tempStruct.contents.quotes[0].length)
quoteViewController.webStruct = tempStruct
//quoteViewController.setupLabels(array: (tempStruct.contents.quotes))
quoteViewController.setupLabels(obj: tempStruct)
} catch let jsonErr {
print("Failed to decode:", jsonErr)
}
}
}.resume()
}