I'm having a hard time accessing data from my JSONDecoder. I see that I am definitely getting a result, but I keep getting an indexOutOfRange error when trying to access the first index.
Model:
struct Movie: Codable {
let page: Int
let results: [Result]
let totalPages, totalResults: Int
enum CodingKeys: String, CodingKey {
case page, results
case totalPages = "total_pages"
case totalResults = "total_results"
}
}
// MARK: - Result
struct Result: Codable, Identifiable {
let adult: Bool
let backdropPath: String
let id: Int
let title: String?
let originalLanguage: String
let originalTitle: String?
let overview, posterPath: String
let mediaType: MediaType
let genreIDS: [Int]
let popularity: Double
let releaseDate: String?
let video: Bool?
let voteAverage: Double
let voteCount: Int
let name, originalName, firstAirDate: String?
let originCountry: [String]?
enum CodingKeys: String, CodingKey {
case adult
case backdropPath = "backdrop_path"
case id, title
case originalLanguage = "original_language"
case originalTitle = "original_title"
case overview
case posterPath = "poster_path"
case mediaType = "media_type"
case genreIDS = "genre_ids"
case popularity
case releaseDate = "release_date"
case video
case voteAverage = "vote_average"
case voteCount = "vote_count"
case name
case originalName = "original_name"
case firstAirDate = "first_air_date"
case originCountry = "origin_country"
}
}
enum MediaType: String, Codable {
case movie = "movie"
case tv = "tv"
}
Main View
struct MainView: View {
#State var movieList: [Movie] = []
#StateObject var network = myNetwork() // <-- for testing
var sampleText = "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout...."
var body: some View {
VStack {
GeometryReader{ proxy in
TabView{
ForEach(0..<5){ num in
VStack {
Button(action: {}) {
Image("Image")
.frame(width: 300, height: 200)
.scaledToFit()
.clipped()
}
Text("\(movieList[0].results)" as String)
.lineLimit(nil)
.foregroundColor(.white)
.multilineTextAlignment(.leading)
.padding()
.frame(width: 300, height: 200)
.background(Rectangle().fill(Color("Grey")).shadow(radius: 1))
}
}
}.tabViewStyle(PageTabViewStyle())
.padding()
.frame(width: proxy.size.width, height: proxy.size.height)
}
.onAppear {
network.getMovies(onCompletion: { (fetchedCity: Movie) in
DispatchQueue.main.async {
self.movieList = [fetchedCity]
}
})
}
}
.padding()
}
}
API:
class movieAPI:ObservableObject{
func getMovies(onCompletion: #escaping ([Movie]) -> ()){
let apiKey = "bb062ca1a1471913abf6b680168fc5ca"
let url = URL(string: "https://api.themoviedb.org/3/trending/all/day?api_key=\(apiKey)")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
let session = URLSession.shared
let dataTask = session.dataTask(with: request, completionHandler: { (data1, response1, error1) -> Void in
guard let data = data1 else {
return
}
do {
let results = try JSONDecoder().decode([Movie].self, from: data)
DispatchQueue.main.async {
let tmp = results[0].results
print("hotel model \(tmp)")
}
onCompletion(results)
} catch {
print("Couldn't decode hotel json \(error.localizedDescription)")
}
})
dataTask.resume()
}
}
Results:
Text("\(movieList[0].results)" as String)
Result: Thread 1: Fatal error: Index out of range
Text("\(movieList.description)")
Result: Movie(page: 1, results: [SliderExample.Result(adult: false, backdropPath: "/rfnmMYuZ6EKOBvQLp2wqP21v7sI.jpg", id: 774752, title: Optional("The Guardians of the Galaxy Holiday Special"), originalLanguage: "en", originalTitle: Optional("The Guardians of the Galaxy Holiday Special"), overview: "On a mission to make Christmas unforgettable for Quill, the Guardians head to Earth in search of the perfect present.", posterPath: "/8dqXyslZ2hv49Oiob9UjlGSHSTR.jpg", mediaType: SliderExample.MediaType.movie, genreIDS: [35, 878, 12], popularity: 539.588, releaseDate: Optional("2022-11-25"), video: Optional(false), voteAverage: 7.521, voteCount: 382, name: nil, originalName: nil, firstAirDate: nil, originCountry: nil)
My goal is to access the overview information.
Related
I'm currently trying to utilize the NewsApi api to allow me to retrieve certain articles. I currently do have a model for which I generated
import Foundation
// MARK: - Welcome
struct NewsResponse: Codable {
let status: String
let totalResults: Int
let articles: [Article]
enum CodingKeys: String, CodingKey {
case status = "status"
case totalResults = "totalResults"
case articles = "articles"
}
}
// MARK: - Article
struct Article: Codable, Identifiable {
let id = UUID()
let source: Source
let author: String?
let title: String
let articleDescription: String
let url: String
let urlToImage: String?
let publishedAt: Date
let content: String
enum CodingKeys: String, CodingKey {
case source = "source"
case author = "author"
case title = "title"
case articleDescription = "description"
case url = "url"
case urlToImage = "urlToImage"
case publishedAt = "publishedAt"
case content = "content"
}
}
// MARK: - Source
struct Source: Codable {
let id: String?
let name: String
enum CodingKeys: String, CodingKey {
case id = "id"
case name = "name"
}
}
I also do have my Webservice that decodes the API link which is at let pokeNews = URL(string:"https://newsapi.org/v2/everything?q=pokemon&apiKey=*APIKey*")!
The webservice code is here and I had used a Mohammed Azam tutorial for that: https://www.youtube.com/watch?v=YOCZuZz4vAw
import Foundation
class NewsWebService: ObservableObject{
#Published var news: [Article] = []
func getNews() async throws{
let (data, _) = try await URLSession.shared.data(from: Constants.url.pokeNews)
Task{#MainActor in
self.news = try JSONDecoder().decode([Article].self, from: data)
}
}
}
Now the main issue I'm having is that I'm at a loss of understanding at how I would access the articles array from the NewsResponse model and retrieve the article.title, etc. I've attempted it multiple times, but am not quite sure how to proceed. I've looked at other tutorials, but I feel that I'm still not gaining a sense of understanding at how to effectively call apis in swift. The code in which I'm attempting to call the API within is here:
import SwiftUI
struct NewsListView: View {
#EnvironmentObject var newsWebService: NewsWebService
var body: some View {
List(newsWebService.news){ article in
Text(article.title)
}
HStack(alignment: .center, spacing: 16, content: {
//Article Image
Image("yak0")
.resizable()
.scaledToFill()
.frame(width: 50, height: 50)
.clipShape(RoundedRectangle(cornerRadius: 12))
//Article Title
VStack(alignment: .leading, spacing: 8){
Text("Massive News Surrounding Pokemon")
.font(.title2)
.fontWeight(.heavy)
.foregroundColor(.red)
//Article Source
Text("CNN").font(.footnote)
.fontWeight(.bold)
.multilineTextAlignment(.leading)
.foregroundColor(.yellow)
}
}).onTapGesture {
//go to webview
}
}
}
struct NewsListView_Previews: PreviewProvider {
static var previews: some View {
NewsListView()
.previewLayout(.sizeThatFits)
.padding()
.environmentObject(NewsWebService())
}
}
Any help would be appreciated. Thank you so much!
Edited for NewsResponse portion
import Foundation
class NewsWebService: ObservableObject{
#Published var news: NewsResponse?
func getNews() async throws{
let (data, _) = try await URLSession.shared.data(from: Constants.url.pokeNews)
Task{#MainActor in
self.news = try JSONDecoder().decode(NewsResponse.self, from: data)
}
}
}
The Line showing the error: Initializer 'init(_:rowContent:)' requires that 'NewsResponse' conform to 'RandomAccessCollection'
List(newsWebService.news!){ article in
Text(article.title)
}
try this example code (note the mods in Article), works well for me. Note, do not show your secret api key, remove it:
struct ContentView: View {
#StateObject var newsWebService = NewsWebService()
var body: some View {
NewsListView().environmentObject(newsWebService)
}
}
struct NewsListView: View {
#EnvironmentObject var newsWebService: NewsWebService
var body: some View {
List(newsWebService.news?.articles ?? []){ article in // <-- here
Text(article.title)
}
.task {
do{
try await newsWebService.getNews()
} catch{
print("---> task error: \(error)")
}
}
}
}
class NewsWebService: ObservableObject{
#Published var news: NewsResponse?
func getNews() async throws {
let (data, _) = try await URLSession.shared.data(from: Constants.url.pokeNews)
Task{#MainActor in
self.news = try JSONDecoder().decode(NewsResponse.self, from: data)
}
}
}
struct NewsResponse: Codable {
let status: String
let totalResults: Int
let articles: [Article]
}
struct Article: Codable, Identifiable {
let id = UUID()
let source: Source
let author: String?
let title, articleDescription: String
let url: String
let urlToImage: String?
let publishedAt: String? // <-- here
let content: String
enum CodingKeys: String, CodingKey {
case source, author, title
case articleDescription = "description"
case url, urlToImage, publishedAt, content
}
}
struct Source: Codable {
let id: String?
let name: String
}
This is assuming Constants.url.pokeNews is the url for "https://newsapi.org/v2/everything?q=pokemon&apiKey=YOURKEY"
EDIT-1:
If you want to use Article, let publishedAt: Date?, instead of String?, then use:
func getNews() async throws {
let (data, _) = try await URLSession.shared.data(from: Constants.url.pokeNews)
Task{#MainActor in
let decoder = JSONDecoder() // <-- here
decoder.dateDecodingStrategy = .iso8601 // <-- here
self.news = try decoder.decode(NewsResponse.self, from: data)
}
}
When I try to present the results I received this message "Response could not be decoded because of error:
The data couldn’t be read because it isn’t in the correct format."
This is my format and its right I think.
import Foundation
// MARK: - Response
struct Response: Codable {
let code: Int
let meta: Meta
let data: [Datum]
}
// MARK: - Datum
struct Datum: Codable {
let id, userID: Int
let title, body: String
enum CodingKeys: String, CodingKey {
case id
case userID = "user_id"
case title, body
}
}
// MARK: - Meta
struct Meta: Codable {
let pagination: Pagination
}
// MARK: - Pagination
struct Pagination: Codable {
let total, pages, page, limit: Int
}
also I try with this code to view the result.
private func fetchData() {
self.task = AF.request(self.baseUrl, method: .get, parameters: nil)
.publishDecodable(type: [Response].self)
.sink(receiveCompletion: {(completion) in
switch completion {
case .finished:
()
case .failure(let error):
print(String(describing: error))
//print(error.localizedDescription)
}
}, receiveValue: {[weak self ](response) in
switch response.result {
case .success(let model): self?.presenters = model.map {PostPresenter(with: $0)}
case.failure(let error):
print(String(describing: error))
// print(error.localizedDescription)
}
})
}
And my post presenter code is this
struct PostPresenter: Identifiable {
let id = UUID()
let title: String
init(with model:Response) {
self.title = model.data
}
}
Two mistakes
The root object is a dictionary so it's (type: Response.self)
and model.data is [Datum] so declare
struct PostPresenter: Identifiable {
let id = UUID()
let data: [Datum]
init(with response: Response) {
self.data = response.data
}
}
And in a Codable context print the error always print(error), not print(String(describing: error)) and never print(error.localizedDescription)
My right Post presenter
struct PostPresenter: Identifiable {
let id = UUID()
let data: [Datum]
init(with response: Response<[Datum]>) {
self.data = response.data
}
init() {
data = []
}
}
And my finally format as I right.
struct Response<T: Decodable>: Decodable {
let code: Int
let meta: Meta
let data: T
}
// MARK: - Datum
struct Datum: Decodable {
let id, userID: Int
let title, body: String
enum CodingKeys: String, CodingKey {
case id
case userID = "user_id"
case title, body
}
}
// MARK: - Meta
struct Meta: Decodable {
let pagination: Pagination
}
// MARK: - Pagination
struct Pagination: Decodable {
let total, pages, page, limit: Int
}
And finally my homeview and how I present
struct HomeView: View {
#ObservedObject var viewModel = HomeAPIViewModel()
var body: some View {
ZStack {
Color(.white)
// Present the API Here
List(self.viewModel.presenter.data, id: \.id) {
Text($0.title)
}
.padding()
}
}
}
import Foundation
class ReadLocalJSON {
static func readJSONFromFile(fileName: String) -> JSON
{
var json: JSON
if let path = Bundle.main.path(forResource: fileName, ofType: "json") {
do {
let fileUrl = URL(fileURLWithPath: path)
let data = try Data(contentsOf: fileUrl, options: .mappedIfSafe)
json = try? JSONSerialization.jsonObject(with: data)
} catch {
print("Something goes wrong when reading local json file.")
}
}
return json
}
}
I try to read the local json file and output json. But the line json = try? JSONSerialization.jsonObject(with: data) gives an error saying Cannot assign value of type 'Any?' to type 'JSON'.
My json data looks like
{
"leagues":
[
{ "name": "Hockey",
"image": "hockey",
"games":
[
{
"game_state": "Final",
"game_time": 1456662600,
"home_team_city": "Alberta",
"home_team_name": "Pigs",
"home_team_score": 1,
"home_team_logo": "pig",
"visit_team_city": "Montreal",
"visit_team_name": "Fishes",
"visit_team_score": 4,
"visit_team_logo": "fish"
}
]
}
]
}
When I change the output type to be Any? I print the output and it seems missing some elements.
{
leagues = (
{
games = (
{
"game_state" = Final;
"game_time" = 1456662600;
...
How can I fix it?
Check the solution below, I used Codable for the JSON decoding.
import Foundation
struct Sports: Codable {
let leagues: [League]
}
struct League: Codable {
let name, image: String
let games: [Game]
}
struct Game: Codable {
let gameState: String
let gameTime: Int
let homeTeamCity, homeTeamName: String
let homeTeamScore: Int
let homeTeamLogo, visitTeamCity, visitTeamName: String
let visitTeamScore: Int
let visitTeamLogo: String
enum CodingKeys: String, CodingKey {
case gameState = "game_state"
case gameTime = "game_time"
case homeTeamCity = "home_team_city"
case homeTeamName = "home_team_name"
case homeTeamScore = "home_team_score"
case homeTeamLogo = "home_team_logo"
case visitTeamCity = "visit_team_city"
case visitTeamName = "visit_team_name"
case visitTeamScore = "visit_team_score"
case visitTeamLogo = "visit_team_logo"
}
}
class ReadLocalJSON {
static func readJSONFromFile(fileName: String) -> Sports?
{
let path = Bundle.main.path(forResource: fileName, ofType: "json")
let url = URL(fileURLWithPath: path!)
let sportsData = try? Data(contentsOf: url)
guard
let data = sportsData
else { return nil }
do {
let result = try JSONDecoder().decode(Sports.self, from: data)
print(result)
return result
} catch let error {
print("Failed to Decode Object", error)
return nil
}
}
}
ReadLocalJSON.readJSONFromFile(fileName: "test")
Step 1:- first make a modal class in your project
struct Welcome: Codable {
let leagues: [League]?
}
// MARK: - League
struct League: Codable {
let name, image: String?
let games: [Game]?
}
// MARK: - Game
struct Game: Codable {
let gameState: String?
let gameTime: Int?
let homeTeamCity, homeTeamName: String?
let homeTeamScore: Int?
let homeTeamLogo, visitTeamCity, visitTeamName: String?
let visitTeamScore: Int?
let visitTeamLogo: String?
enum CodingKeys: String, CodingKey {
case gameState = "game_state"
case gameTime = "game_time"
case homeTeamCity = "home_team_city"
case homeTeamName = "home_team_name"
case homeTeamScore = "home_team_score"
case homeTeamLogo = "home_team_logo"
case visitTeamCity = "visit_team_city"
case visitTeamName = "visit_team_name"
case visitTeamScore = "visit_team_score"
case visitTeamLogo = "visit_team_logo"
}
}
Step 2 : - After getting response write this line,
let decoder = JSONDecoder()
let obj = try! decoder.decode(Welcome.self, from: jsonData!)
IF you have still problem let me know
I have to read a json from the url: https://randomuser.me/api/?results=100
I created the People.swift file that contains the structure created through the site: https://app.quicktype.io/?l=swift
I tried to use this code but I can not then insert the json into the structure and then recall it via cell.people.name for example.
ViewController.swift:
var dataRoutine = [People]() // this is the structure that I created with the site indicated above.
this one is my function to download the Json and parse.
func downloadJsonData(completed : #escaping ()->()){
guard let url = URL(string: "https://randomuser.me/api/?results=100")else {return}
let request = URLRequest.init(url: url)
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let httpResponse = response as? HTTPURLResponse {
let statuscode = httpResponse.statusCode
if statuscode == 404{
print( "Sorry! No Routine Found")
}else{
if error == nil{
do{
self.dataRoutine = try JSONDecoder().decode(People.self, from: data!)
DispatchQueue.main.async {
completed()
print(self.dataRoutine.count) // I don't know why my result is ever 1.
}
}catch{
print(error)
}
}
}
}
}.resume()
}
my structure is :
import Foundation
struct People: Codable {
let results: [Result]?
let info: Info?
}
struct Info: Codable {
let seed: String?
let results, page: Int?
let version: String?
}
struct Result: Codable {
let gender: Gender?
let name: Name?
let location: Location?
let email: String?
let login: Login?
let dob, registered: Dob?
let phone, cell: String?
let id: ID?
let picture: Picture?
let nat: String?
}
struct Dob: Codable {
let date: Date?
let age: Int?
}
enum Gender: String, Codable {
case female = "female"
case male = "male"
}
struct ID: Codable {
let name: String?
let value: String?
}
struct Location: Codable {
let street, city, state: String?
let postcode: Postcode?
let coordinates: Coordinates?
let timezone: Timezone?
}
struct Coordinates: Codable {
let latitude, longitude: String?
}
enum Postcode: Codable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Postcode.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Postcode"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
struct Timezone: Codable {
let offset, description: String?
}
struct Login: Codable {
let uuid, username, password, salt: String?
let md5, sha1, sha256: String?
}
struct Name: Codable {
let title: Title?
let first, last: String?
}
enum Title: String, Codable {
case madame = "madame"
case mademoiselle = "mademoiselle"
case miss = "miss"
case monsieur = "monsieur"
case mr = "mr"
case mrs = "mrs"
case ms = "ms"
}
struct Picture: Codable {
let large, medium, thumbnail: String?
}
The main issue is a type mismatch.
The root object of the JSON is not the People array, it's the umbrella struct, I named it Response
Please change the structs to
struct Response: Decodable {
let results: [Person]
let info: Info
}
struct Info: Decodable {
let seed: String
let results, page: Int
let version: String
}
struct Person: Decodable {
let gender: Gender
let name: Name
let location: Location
let email: String
let login: Login
let dob, registered: Dob
let phone, cell: String
let id: ID
let picture: Picture
let nat: String
}
struct Dob: Decodable {
let date: Date
let age: Int
}
enum Gender: String, Decodable {
case female, male
}
struct ID: Codable {
let name: String
let value: String?
}
struct Location: Decodable {
let street, city, state: String
let postcode: Postcode
let coordinates: Coordinates
let timezone: Timezone
}
struct Coordinates: Codable {
let latitude, longitude: String
}
enum Postcode: Codable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Postcode.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Postcode"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
struct Timezone: Codable {
let offset, description: String
}
struct Login: Codable {
let uuid, username, password, salt: String
let md5, sha1, sha256: String
}
struct Name: Codable {
let title: Title
let first, last: String
}
enum Title: String, Codable {
case madame, mademoiselle, miss, monsieur, mr, mrs, ms
}
struct Picture: Codable {
let large, medium, thumbnail: String
}
Almost all properties can be declared non-optional, the date key in Dob is an ISO8601 date string you have to add the appropriate date decoding strategy. The People array is the property results of the root object.
var dataRoutine = [Person]()
func downloadJsonData(completed : #escaping ()->()){
guard let url = URL(string: "https://randomuser.me/api/?results=100")else {return}
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let httpResponse = response as? HTTPURLResponse {
let statuscode = httpResponse.statusCode
if statuscode == 404{
print( "Sorry! No Routine Found")
}else{
if error == nil{
do{
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let jsonResponse = try decoder.decode(Response.self, from: data!)
self.dataRoutine = jsonResponse.results
DispatchQueue.main.async {
completed()
print(self.dataRoutine.count) // I don't know why my result is ever 1.
}
}catch{
print(error)
}
}
}
}
}.resume()
}
This is the code I am using but I am unable to fetch the JSON.
Error message:
Expected to decode Dictionary<String, Any> but found an array instead.
func getMovieByName(completion: #escaping (Bool, Any?, Error?) -> Void) {
guard let url = URL(string:"https://api.themoviedb.org/3/search/movie?api_key=4cb1eeab94f45affe2536f2c684a5c9e&query='star") else { return }
let session = URLSession.shared
let task = session.dataTask(with: url) { (data, _, _) in
guard let data = data else { return }
do {
let items = try JSONDecoder().decode(ItemList.self, from: data)
DispatchQueue.main.async {
completion(true, items, nil)
}
} catch {
DispatchQueue.main.async {
completion(false, nil, error)
}
}
}
task.resume()
}
JSON:
{
"page": 1,
"total_results": 2102,
"total_pages": 106,
"results": [{
"vote_count": 9052,
"id": 11,
"video": false,
"vote_average": 8.2,
"title": "Star Wars",
"popularity": 31.502792,
"poster_path": "/btTdmkgIvOi0FFip1sPuZI2oQG6.jpg",
"original_language": "en",
"original_title": "Star Wars",
"genre_ids": [
12,
28,
878
],
"backdrop_path": "/4iJfYYoQzZcONB9hNzg0J0wWyPH.jpg",
"adult": false,
"overview": "Princess Leia is captured and held hostage by the evil Imperial forces in their effort to take over the galactic Empire. Venturesome Luke Skywalker and dashing captain Han Solo team together with the loveable robot duo R2-D2 and C-3PO to rescue the beautiful princess and restore peace and justice in the Empire.",
"release_date": "1977-05-25"
}]
}
struct Results: Codable {
let id: Int
let title: String
let poster_path: String
struct ItemList: Codable {
let results: Results
}
}
You can create a Swift Struct for this purpose. Here is how you do it.
import Foundation
struct MovieStruct: Codable {
let page, totalResults, totalPages: Int?
let results: [Result]?
enum CodingKeys: String, CodingKey {
case page
case totalResults = "total_results"
case totalPages = "total_pages"
case results
}
}
struct Result: Codable {
let voteCount, id: Int?
let video: Bool?
let voteAverage: Double?
let title: String?
let popularity: Double?
let posterPath, originalLanguage, originalTitle: String?
let genreIDS: [Int]?
let backdropPath: String?
let adult: Bool?
let overview, releaseDate: String?
enum CodingKeys: String, CodingKey {
case voteCount = "vote_count"
case id, video
case voteAverage = "vote_average"
case title, popularity
case posterPath = "poster_path"
case originalLanguage = "original_language"
case originalTitle = "original_title"
case genreIDS = "genre_ids"
case backdropPath = "backdrop_path"
case adult, overview
case releaseDate = "release_date"
}
}
After you have created the struct, you can do something like this to parse your data.
func getMovieByName(completion: #escaping (Bool, Any?, Error?) -> Void) {
guard let url = URL(string:"https://api.themoviedb.org/3/search/movie?api_key=4cb1eeab94f45affe2536f2c684a5c9e&query='star") else { return }
let session = URLSession.shared
let task = session.dataTask(with: url) { (data, _, _) in
guard let data = data else { return }
do {
let items = try? JSONDecoder().decode(MovieStruct.self, from: jsonData)
DispatchQueue.main.async {
completion(true, items, nil)
}
} catch {
DispatchQueue.main.async {
completion(false, nil, error)
}
}
}
task.resume()
}
Note I have created the struct with the JSON which you have given. I hope it helps.
func getMovieByName(completion: #escaping (Bool, Any?, Error?) -> Void) {
guard let url = URL(string:"https://api.themoviedb.org/3/search/movie?api_key=4cb1eeab94f45affe2536f2c684a5c9e&query='star") else { return }
let session = URLSession.shared
let task = session.dataTask(with: url) { (data, _, _) in
guard let data = data else { return }
do {
let items = try JSONDecoder().decode(Result.self, from: data)
DispatchQueue.main.async {
completion(true, items, nil)
}
} catch {
DispatchQueue.main.async {
completion(false, nil, error)
}
}
}
task.resume()
}
Result struct contains the contents of "results"
struct Result: Codable {
var results: [Movie]
}
Add variables to correspond to the item's fields
struct Movie: Codable {
var id: Int
var vote_count: Int
var title: String
//etc..
}