Ошибка декодера 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