Ошибка декодера JSON при декодировании в CollectionView

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

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

Swift.DecodingError.dataCorrupted (Swift.DecodingError.Context (codingPath: [], debugDescription: "Указанные данные не были действительными в формате JSON.", UnderError: Необязательный (Ошибка домена =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 ответа

Решение

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

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

Вы получаете эту ошибку, потому что вы не получили данные 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

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

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)
}

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

Название: Военно-морской пирс IMAX Theatre

Другие вопросы по тегам