Заполнение табличного представления из структур вместо массивов - PullRequest
0 голосов
/ 22 октября 2018

Я делаю небольшой проект, чтобы попрактиковаться в сериализации JSON в Swift 4 с использованием структур ... он получает главные новости из API New York Times и помещает их в табличное представление.В настоящее время я получаю необходимые данные из JSON и заполняю некоторые массивы необходимыми материалами (заголовки, аннотации и т. Д.).

Кто-то посоветовал мне пропустить этот шаг и вместо этого заполнить табличное представление непосредственно изструктуры.

struct TopStoriesResponse: Decodable {
    let status: String
    let results: [Story]
}

struct Story: Decodable {
    let title: String
    let abstract: String
    let url: String
    let multimedia: [Multimedia]

    private enum CodingKeys: String, CodingKey {
        case title
        case abstract
        case url
        case multimedia
    }

    init(from decoder:Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        title = try container.decode(String.self, forKey: .title)
        abstract = try container.decode(String.self, forKey: .abstract)
        url = try container.decode(String.self, forKey: .url)
        multimedia = (try? container.decode([Multimedia].self, forKey: .multimedia)) ?? []
    }

}

struct Multimedia: Decodable {
    let url: String
    let type: String
}

var storyData = [Story]()

И в моем методе cellForRowAt:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "storyCell", for: indexPath) as! StoryTableViewCell

    let stories = storyData[indexPath.row]

    print("Titles: \(stories.title)")

    cell.headlineLabel.text = stories.title
    cell.abstractLabel.text = stories.abstract

    return cell
}

Когда я запускаю приложение, представление таблицы пустое, и мой оператор печати подтвердил, что stories.titleпусто (все показывалось раньше, когда я использовал массивы).

Это функция, которая захватывает данные, если она применима здесь, я вычеркну весь код, который передает данные в массивы, если я смогу использоватьвместо этого Structs:

func getJSON(completionHandler: @escaping (Bool) -> ()) {
    let jsonUrlString = "https://api.nytimes.com/svc/topstories/v1/business.json?api-key=f4bf2ee721031a344b84b0449cfdb589:1:73741808"
    guard let url = URL(string: jsonUrlString) else {return}

    URLSession.shared.dataTask(with: url) { (data, response, err) in
        guard let data = data, err == nil else {
            print(err!)
            return
        }

        do {
            let response = try
                JSONDecoder().decode(TopStoriesResponse.self, from: data)

            // Pass results into arrays (title, abstract, url, image)
            for result in response.results {
                let headlines = result.title
                let abstracts = result.abstract
                let url = result.url

                self.headlines.append(headlines)
                self.abstracts.append(abstracts)
                self.urls.append(url)

                for imageResults in result.multimedia {
                    let images = imageResults.url
                    self.images.append(images)
                }
            }

            completionHandler(true)

        } catch let jsonErr {
            print("Error serializing JSON", jsonErr)
        }
    }.resume()
}

Нужно ли передавать данные обратно в структуры, как я делал это с массивами?У меня сложилось впечатление, что let response = try JSONDecoder().decode(TopStoriesResponse.self, from: data) уже сделал это.

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Кажется, в ваших моделях данных есть несоответствие.С одной стороны, ваши данные JSON помещаются в четыре массива: self.headlines, self.abstracts, self.urls и self.images.Но ваше табличное представление ничего не знает об этом;это полностью зависит от другого массива, storyData.Вам нужно объединить эти две модели данных, если вы понимаете, о чем я.Загрузите данные, перенастройте их в storyData, а затем передайте в табличное представление значение reloadData.

0 голосов
/ 22 октября 2018

Вам нужно

let response = try  JSONDecoder().decode(TopStoriesResponse.self, from: data)
self.storyData = response.results
DispatchQueue.main.async {
  self.tableView.reloadData()
}

содержимое других массивов здесь не имеет значения, так как вы не используете их в качестве источника данных таблицы

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