Here I’m creating a simple movie app (one screen) to display the list of movies under “Now Playing” In the Theatres Category. And I’m going to use a networking layer with URLSession class, To make an API call and fetch JSON data. you can create a networking layer using the URLSession class.

Let’s build our steps here,

  1. Observe the JSON response from the API Endpoint.
  2. Create a struct model based on the API JSON Response.
  3. Create a Network-Layer to handle the API call.
  4. Create a view to display the result from the network layer.

About API Endpoint:

For this tutorial, we will use TMDB API, Signup and Login to https://www.themoviedb.org/, go to My Account -> Settings -> API, create a new APP, and it will generate an API key

Once you get the API KEY, we will use the endpoint URL like https://api.themoviedb.org/3/movie/now_playing?api_key=<API KEY>&language=en-US&page=1 and the response will be as follows:

{
	.
        .
	"results": [{
		"id": 315162,
		"original_language": "en",
		"original_title": "Puss in Boots: The Last Wish",
		"overview": "Puss in Boots discovers that his passion for adventure has taken its toll: He has burned through eight of his nine lives, leaving him with only one life left. Puss sets out on an epic journey to find the mythical Last Wish and restore his nine lives.",
		"poster_path": "/1NqwE6LP9IEdOZ57NCT51ftHtWT.jpg",
		"title": "Puss in Boots: The Last Wish",
                .
                .
	}, 
         .
         .
         ],
}

From the above movie data, we are going to use the elements, id, title, overview, and poster_path. Here if you closely look at poster_path, the image URL was incomplete, so we need to concatenate https://image.tmdb.org/t/p/w600_and_h900_bestv2/ to the poster_path while reading the data, and now our final URL will be

https://image.tmdb.org/t/p/w600_and_h900_bestv2/1NqwE6LP9IEdOZ57NCT51ftHtWT.jpg

Here we completed observing the response structure, And now let’s create a model for the JSON response (2nd step).

Create a new Group, “Models,” in your Xcode project and create a file Movie.swift in it.

import Foundation

struct MovieResponse: Decodable {
    let results: [Movie]
}

struct Movie: Decodable, Identifiable {

    let id: Int
    let movieTitle: String
    let movieDescription: String
    let poster: String
    var moviePoster: URL {
        return URL(string: "https://image.tmdb.org/t/p/w1280/\(poster)")!
    }

    private enum CodingKeys: String, CodingKey {
        case id = "id"
        case movieTitle = "title"
        case movieDescription = "overview"
        case poster = "poster_path"
    }
}

In the above model, struct Movie is for the movie item, and the struct MovieResponse is the array of Movie items from the API response. Here we are doing key customization for easy key reading; hence we did CodingKey Enum Mapping on the JSON elements. And here, we implemented a new element called moviePoster, which returns the full poster path to showcase the image.

Now let’s move to 3rd step of creating a Network Layer. In this step, we will implement the fetchMovies function responsible for making an API call and returning the Movies Object.

Create a new Group, “Network,” in your Xcode project and create a NetworkModel.swift file.

import Foundation

struct MovieEndPoints{
    static let playNowEndPoint: String = "https://api.themoviedb.org/3/movie/now_playing?api_key=4f6a32982b71292047a86d70d3fd2842&language=en-US&page=1"
}

class NetworkModel: ObservableObject {
    @Published var movies: [Movie] = []
    
    func fetchMovies() async throws {
        if let url = URL(string: MovieEndPoints.playNowEndPoint) {
            let request = URLRequest(url: url)
            let (data, _) = try await URLSession.shared.data(for: request)
            let movieResponse = try JSONDecoder().decode(MovieResponse.self, from: data)
            movies = movieResponse.results
        }
    }
}

I’ve included a struct MovieEndPoints containing static API endpoints in this file.

We use URLSession to make an API request and catch the data. Later we do Decode the response by using JSONDecoder, and return movies objects with the “Now Playing” movies list.

Now time to read the serialized response from the fetchMovies method and render the data (now playing movies) in the View.

For the final step, let’s create the View, which is a swiftUI based.

//
//  ContentView.swift
//  playnowmovies
//
//  Created by ThotaMac16's MacBook Pro on 12/1/23.
//

import SwiftUI

struct ContentView: View {

    @StateObject private var network = NetworkModel()
    var body: some View {
        NavigationStack {
            VStack {
                Text("Now Playing")
                    .font(.title)
                    .bold()
                List(network.movies) { movies in
                    VStack {
                            AsyncImage(url: movies.moviePoster) { image in
                                image.resizable()
                                    .aspectRatio(contentMode: .fill)
                                    //.frame(maxHeight: 300)
                                
                            } placeholder: {
                                Text("...")
                            }
                            Text(movies.movieTitle)
                            .font(.title2)
                                .padding()

                        Text(movies.movieDescription)
                            .font(.caption)
                    }
                }.task {
                    do {
                        try await network.fetchMovies()
                    } catch {
                        print(error)
                    }
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

And the view looks like,

 

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *