Получить JSON, разобрать его в массив и распечатать в Swift.

Я пытаюсь получить данные json из API, разобрать их в массив структур и распечатать массив. Но когда я пытаюсь его распечатать, возвращается только пустой массив. Я пытаюсь понять, как писать код для асинхронных операций, и не знаю, куда идти дальше. Может ли кто-нибудь указать мне правильное направление? Я пробую это на игровых площадках, используя Xcode 9, Swift 4.

import Foundation

struct Item: Decodable {
    var userId: Int?
    var id: Int?
    var title: String?
    var body: String?
}

var items = [Item?]()

let completionHandler = { (data: Data?, response: URLResponse?, error: Error?) in
        if error != nil {
            print("Error occured: \(error.debugDescription)")
        }
        
        let decoder = JSONDecoder()
        do {
            items = try decoder.decode([Item].self, from: data!)
            print(items)
        } catch {
            print("Error: Unable to fetch data")
        }
    }

func getJson() {
    let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
    let session = URLSession.shared
    let task = session.dataTask(with: url, completionHandler: completionHandler)
    task.resume()
    print(items)
}

getJson()


person ram    schedule 04.09.2018    source источник
comment
Печатает ли что-нибудь print(items) внутри completionHandler?   -  person ielyamani    schedule 04.09.2018
comment
Если это не так, это означает, что ваш Item не настроен должным образом для вашего JSON.   -  person Rakesha Shastri    schedule 04.09.2018


Ответы (1)


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

import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

Три примечания:

  1. Строка print после resume бессмысленна. Он всегда будет печатать пустой массив. Строка print в обработчике завершения показывает реальный результат
  2. Объявить items как

    var items = [Item]()
    

    JSONDecoder() возвращает что-то обязательное или выдает ошибку

  3. Этот конкретный API всегда отправляет все поля, поэтому вы даже можете объявить все элементы структуры необязательными.

    struct Item: Decodable {
        var userId: Int
        var id: Int
        var title: String
        var body: String
    }
    
person vadian    schedule 04.09.2018
comment
Спасибо @vadian. Это работает. Далее я собирался работать с массивом 'items' внутри getJson(). Но я понимаю, что это невозможно. И, поскольку обработчик завершения dataTask ничего не возвращает, я не могу с ним работать и там. Если это не слишком много, чтобы задать этот вопрос, не могли бы вы также сказать мне, где и как это сделать? - person ram; 04.09.2018
comment
Спасибо и за три заметки, @vadian. Они помогли мне лучше понять концепции. - person ram; 04.09.2018
comment
Просто делайте то, что хотите — например, заполняйте массив источников данных и перезагружайте таблицу — в обработчике завершения, а не в строке печати. - person vadian; 04.09.2018