Сетевой запрос не возвращает данные

request

#1

пытаюсь реализовать в Playground тестовый пример получения данных с сайта iTunes. Но данные не приходят, не могу понять почему.

import UIKit
import PlaygroundSupport

extension URL {
    
    func withQueries(_ queries: [String: String]) -> URL? {
        var components = URLComponents(url: self, resolvingAgainstBaseURL: true)
        components?.queryItems = queries.map {
            URLQueryItem(name: $0.0, value: $0.1)
        }
        return components?.url
    }
}

struct StoreItem: Codable {

    var title: String
    var artist: String?

    enum CodingKeys: String, CodingKey {

        case title = "term"
        case artist = "media"
    }

    init(from decoder: Decoder) throws {

        let valueContainer = try decoder.container(keyedBy: CodingKeys.self)

        self.title = try valueContainer.decode(String.self, forKey: CodingKeys.title)
        self.artist = try valueContainer.decode(String.self, forKey: CodingKeys.artist)
    }
}

PlaygroundPage.current.needsIndefiniteExecution = true

func fetchInfo(completion: @escaping (StoreItem?) -> Void) {
    
    let baseURL = URL(string: "https://itunes.apple.com/search?")!
    
    let query: [String: String] = [
        
        "term": "Beatles",
        "media": "musicVideo"
    ]
    
    let url = baseURL.withQueries(query)!
    
    let task = URLSession.shared.dataTask(with: url) {
        (data, response, error) in
        
        let jsonDecoder = JSONDecoder()
        
        if let data = data, let string = try?  jsonDecoder.decode(StoreItem.self, from: data) { completion(string)
            
        } else {
            print("Either no data was returned, or data was not properly decoded.")
            
            completion (nil)
        }
        PlaygroundPage.current.finishExecution()
    }
    task.resume()
}

fetchInfo { (fetchedInfo) in
    print(fetchedInfo)
}

Подозреваю, что проблема в структуре запроса, которая let query. И здесь свои непонятки. На сайте в описании ключевых параметров для запроса указано одни примеры, а в результатах запроса их нет, а есть другие. Например, term есть в ключевых параметрах, но нет в результатах. И наоборот, kind есть в результатах, но нет в ключевых параметрах. Как это вообще соотносится друг с другом?


#2

На первый взгляд у тебя проверки на ошибку нет, и ты ее ни как не обрабатываешь, посмотри, может ее ловишь)


#3

обработка вроде есть, выдает сообщение, что “Either no data was returned, or data was not properly decoded.” Но она такого общего плана.


#4

У вас запрос такой - https://itunes.apple.com/search?term=Beatles&media=musicVideo ?
Кинул запрос в Постман гетом. Получил ответ

{
"resultCount": 50,
"results": [
    {
        "wrapperType": "track",
        "kind": "music-video",
        "artistId": 136975,
        "collectionId": 1441164426,
        "trackId": 1441164605,
        "artistName": "The Beatles",
        "collectionName": "Abbey Road (Remastered)",
        "trackName": "Abbey Road (Documentary)",
        "collectionCensoredName": "Abbey Road (Remastered)",
        "trackCensoredName": "Abbey Road (Documentary)",
        "artistViewUrl": "https://music.apple.com/us/artist/the-beatles/136975?uo=4",
        "collectionViewUrl": "https://music.apple.com/us/music-video/abbey-road-documentary/1441164605?uo=4",
        "trackViewUrl": "https://music.apple.com/us/music-video/abbey-road-documentary/1441164605?uo=4",
        "previewUrl": "https://video-ssl.itunes.apple.com/itunes-assets/Video118/v4/36/6e/3e/366e3ef3-c6c6-1f48-0ee5-bf668e1636ad/mzvf_3662558786711405799.640x480.h264lc.U.p.m4v",
        "artworkUrl30": "https://is1-ssl.mzstatic.com/image/thumb/Video118/v4/ac/bf/d9/acbfd990-a0cc-2654-7556-d53dae8b762f/source/30x30bb.jpg",
        "artworkUrl60": "https://is1-ssl.mzstatic.com/image/thumb/Video118/v4/ac/bf/d9/acbfd990-a0cc-2654-7556-d53dae8b762f/source/60x60bb.jpg",
        "artworkUrl100": "https://is1-ssl.mzstatic.com/image/thumb/Video118/v4/ac/bf/d9/acbfd990-a0cc-2654-7556-d53dae8b762f/source/100x100bb.jpg",
        "collectionPrice": 12.99,
        "trackPrice": 1.49,
        "releaseDate": "2019-05-22T07:00:00Z",
        "collectionExplicitness": "notExplicit",
        "trackExplicitness": "notExplicit",
        "discCount": 1,
        "discNumber": 1,
        "trackCount": 19,
        "trackNumber": 18,
        "trackTimeMillis": 232000,
        "country": "USA",
        "currency": "USD",
        "primaryGenreName": "Rock"
    },
... 
 ]
}

Если все данные правильные, то вы неправильно парсите


#5

структура не верная StoreItem


#6

а что именно в ней неправильно?


#7

тот же вопрос - где эта ошибка?


#8

Посмотрите какую модель и какие ключи возвращает сервер, а как вы их парсите. Посмотрите курс или почитайте как это правильно делается


#9

Ну так вы сами посмотрите на ответ сервера и на вашу модель. Там все очевидно.
Мне чисто интересно, как вы создавали вашу модель, по каким критериям/факторам?


#10

тут все достаточно просто. Я в этой теме только начинаю разбираться, поэтому делал по образцу. Образец работает, а этот вариант нет.

По поводу ответа сервера - его как раз в данном случае нет. Выше написал, что смотрел инструкции на самом сайте, где ключевые параметры запроса не совпадают с результатами. Не понимаю, как это соотносится между собой.


#11

курс да, надо посмотреть. А что почитать посоветуете?


#12

Любой вариант


#13

минимум примерно так должно быть:

import UIKit
import PlaygroundSupport

extension URL {

func withQueries(_ queries: [String: String]) -> URL? {
    var components = URLComponents(url: self, resolvingAgainstBaseURL: true)
    components?.queryItems = queries.map {
        URLQueryItem(name: $0.0, value: $0.1)
      }
      return components?.url
  }
}

struct Results: Decodable {
    var results: [StoreItem]

  struct StoreItem: Decodable  {
      var trackName: String
      var artistName: String
  }
}

PlaygroundPage.current.needsIndefiniteExecution = true

func fetchInfo(completion: @escaping (Results?) -> Void) {

let baseURL = URL(string: "https://itunes.apple.com/search?")!

let query: [String: String] = [
    "term": "Beatles",
    "media": "musicVideo"
]

let url = baseURL.withQueries(query)!

let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
    
    let jsonDecoder = JSONDecoder()
    if let data = data, let string = try? jsonDecoder.decode(Results.self, from: data) {
        completion(string)
    } else {
        print("Either no data was returned, or data was not properly decoded.")
        
        completion(nil)
    }
     PlaygroundPage.current.finishExecution()
    }
    task.resume()
}

fetchInfo { (fetchedInfo) in
  print(fetchedInfo)
}

#14

Спасибо! То, что надо!


#15

Вы хоть поняли причину ошибки? У вас уже много тем было по парсингу json ответов. А это не самая сложная тема.


#16

в том то и дело, что нет. Вопросов много, но первый, который тормозит все остальное - где увидеть структуру данных JSON на сайте? Почему, например, в запросе отсылаются одни названия полей, а приходит целая куча совсем других? Почему там на сайте есть ключевые параметры запроса, которые не совпадают с результатами запроса?


#17

Это вы о чем? Это мои первые разборки с данной темой.


#18

и заодно уже до кучи. В инструкции, по которой пытаюсь реализовать эту задачу, говорится о свойстве description.

"You might have noticed that an item can have different types of descriptions.”

Но нигде, ни на сайте, ни в результатах запросов, такого свойства нет.


#19

json ключи можно увидеть, если пройти по ссылке, ВАШ URL https://itunes.apple.com/search?term=Beatles&media=musicVideo ну так посмотрите что внутри. Для таких целей очень удобен Postman https://www.getpostman.com/, скачайте его и наслаждайтесь. А сама сборка URL запроса собирается по документации разработчика, тот кто предоставляет вам API.


#20

Postman - это вещь! Спасибо! И спасибо всем, кто пытался помочь разобраться.

Публикуя этот пост предполагал, что мне просто укажут ошибку. Но оказалось, что это только верхушка айсберга.

В общем, пошел учить матчасть.