Ошибка декодера JSON при декодировании в CollectionView - PullRequest
0 голосов
/ 07 декабря 2018

Я беру массив URL-адресов и декодирую их в представлении коллекции.Я успешно завершил это раньше, но на этот раз получаю ошибку.

Я получаю сообщение об ошибке:

Swift.DecodingError.dataCorrupted (Swift.DecodingError.Context (codingPath:[], debugDescription: «Указанные данные не были действительными в формате JSON.», underError: Необязательный (Ошибка Domain = NSCocoaErrorDomain Code = 3840 «Текст JSON не начинался с массива или объекта, и параметр, позволяющий не устанавливать фрагменты." UserInfo = {NSDebugDescription= JSON-текст не начинался с массива или объекта и опции, позволяющей не задавать фрагменты.})))

Что я замечаю, так это то, что он пытается декодировать один до завершения другого,если возможно.Я верю в это, потому что в некоторых случаях, когда я запускаю приложение, оно печатает один или два экземпляра декодированных данных, а затем выдает ошибку.

Вот мой код:

struct Details: Codable {
    let name: String
    let location: Location
}

struct Location: Codable {
    let address: Address
    let geoCode: Geo
}

struct Geo: Codable {
    let latitude: String
    let longitude: String
}

struct Address: Codable {
    let street: String
    let state: String
    let city: String
    let postalCode: String
    let country: String
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

 let cell = showtimesCollection.dequeueReusableCell(withReuseIdentifier: "timeCell", for: indexPath) as! TimeCell

let theaters = self.theaterIds[indexPath.row]
    let id = theaters
    let apiKey = ""
    let url = URL(string: "http://data.tmsapi.com/v1.1/theatres/\(id)?api_key=\(apiKey)")
    print(url!)
    let request = URLRequest(
        url: url! as URL,
        cachePolicy: URLRequest.CachePolicy.reloadIgnoringLocalCacheData,
        timeoutInterval: 10 )

    let session = URLSession (
        configuration: URLSessionConfiguration.default,
        delegate: nil,
        delegateQueue: OperationQueue.main
    )

    let task = session.dataTask(with: request, completionHandler: { (data, response, error) in
        if let data = data {
            do { let theater = try JSONDecoder().decode(Details.self, from: data) //error: Swift.DecodingError.dataCorrupted
                print(theater)

            } catch let err {
                print("JSON Error")
        }
    })

    task.resume()

return cell }

Массив выглядит так:

["12345", "23456", "34567", "45678"]

Массив правильно печатает на консоль, и поэтому URL-адреса декодируются.Они выглядят так же, как один контроллер, чтобы это работало успешно.

JSON выглядит так:

{
"theatreId": "2469",
"name": "Paramount Theatre",
"location": {
    "telephone": "512-472-5470",
    "geoCode": {
        "latitude": "30.2694",
        "longitude": "-97.7419"
    },
    "address": {
        "street": "713 Congress Ave",
        "state": "TX",
        "city": "Austin",
        "country": "USA",
        "postalCode": "78701"
    }
}
}

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

РЕДАКТИРОВАТЬ: я добавил блок catch в JSONDecoder, и я получаю любой случай ошибки случайно для каждого вызова.Это выглядит примерно так каждый раз, когда я запускаю приложение.

JSON Error
JSON Error
JSON Error
JSON Error
Details(name: "Paramount Theatre", location: Film_Bee.ShowtimesView.Location(address: Film_Bee.ShowtimesView.Address(street: "1245 Station Place", state: "TX", city: "Austin", postalCode: "12345", country: "USA"), geoCode: Film_Bee.ShowtimesView.Geo(latitude: "43.12345", longitude: "-44.12345")))
JSON Error

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

РЕДАКТИРОВАТЬ: Я решилвыпустите решение и разместите решение в качестве ответа.

Другое решение заключается в установке задержки между каждым вызовом.Как мне этого добиться?

Ответы [ 3 ]

0 голосов
/ 07 декабря 2018

Итак, я попробовал этот код:

let data = """
{
    "theatreId": "7719",
    "name": "Navy Pier IMAX Theatre",
    "location": {
        "telephone": "312-595-5629",
        "geoCode": {
            "latitude": "41.8921",
            "longitude": "-87.6088"
        },
        "address": {
            "street": "600 E. Grand Ave. Ste 115",
            "state": "IL",
            "city": "Chicago",
            "country": "USA",
            "postalCode": "60611"
        }
    }
}
""".data(using: .utf8)!
do {
    let theater = try JSONDecoder().decode(Details.self, from: data)
    print("Name: \(theater.name)")
} catch {
    print(error)
}

и ваш код работает, он дал мне следующий вывод:

Имя: Navy Pier IMAX Theatre

0 голосов
/ 07 декабря 2018

Проблема в том, что API разрешает только 2 вызова в секунду, и я пытаюсь сделать больше, чем это.

Чтобы решить эту проблему, мне придется обновить мою учетную запись с помощью tmsapi.

0 голосов
/ 07 декабря 2018

Вы получаете эту ошибку, потому что вы не получили данные JSON.Не забудьте проверить состояние HTTP, например, следующий код

let url = URL(string: "http://data.tmsapi.com/v1.1/theatres/\(2469)?api_key=\(apiKey)")!

URLSession.shared.dataTask(with: url) { (data, response, error) in

    if error == nil, data != nil, let rep = response as? HTTPURLResponse {

        switch rep.statusCode {
        case 200:
            if let theater = try? JSONDecoder().decode(Details.self, from: data!) {
                print(theater)
            }
        default:
            print("Receive HTTP status: \(rep.statusCode)")
            print(String(data: data!, encoding: .utf8))
            print(rep.statusCode)
        }
    } else {
        print(error)
    }
}.resume()

Поскольку для этой конечной точки ответ API:

<h1>Not Authorized</h1>

с кодом состояния 403

...