├── .DS_Store
├── .gitattributes
├── movieui.png
├── TMDBMovieApp
├── Assets.xcassets
│ ├── Contents.json
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── String+Extension.swift
├── TMDBMovieAppApp.swift
├── ContentView.swift
├── Screens
│ ├── MovieDetail
│ │ ├── CastModel.swift
│ │ ├── MovieDetailsViewModel.swift
│ │ └── MovieDetailsView.swift
│ ├── Search
│ │ ├── MovieSearchViewModel.swift
│ │ └── MovieSearchView.swift
│ └── Home
│ │ ├── MovieView.swift
│ │ ├── HomeView.swift
│ │ └── HomeViewModel.swift
└── API
│ ├── EndPointType.swift
│ ├── HomeRowView.swift
│ ├── APIManager.swift
│ ├── MovieEndPoint.swift
│ └── MovieModel.swift
├── TMDBMovieApp.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── yogeshpatel.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
├── xcuserdata
│ └── yogeshpatel.xcuserdatad
│ │ ├── xcschemes
│ │ └── xcschememanagement.plist
│ │ └── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
└── project.pbxproj
└── README.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YogeshPateliOS/TMDBMovieApp/HEAD/.DS_Store
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/movieui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YogeshPateliOS/TMDBMovieApp/HEAD/movieui.png
--------------------------------------------------------------------------------
/TMDBMovieApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/TMDBMovieApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/TMDBMovieApp.xcodeproj/project.xcworkspace/xcuserdata/yogeshpatel.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YogeshPateliOS/TMDBMovieApp/HEAD/TMDBMovieApp.xcodeproj/project.xcworkspace/xcuserdata/yogeshpatel.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/TMDBMovieApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/TMDBMovieApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/TMDBMovieApp/String+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+Extension.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import Foundation
9 |
10 | extension String {
11 |
12 | var imageURL: URL? {
13 | URL(string: "https://image.tmdb.org/t/p/original/\(self)")
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/TMDBMovieApp/TMDBMovieAppApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TMDBMovieAppApp.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct TMDBMovieAppApp: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | HomeView()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/TMDBMovieApp.xcodeproj/xcuserdata/yogeshpatel.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TMDBMovieApp.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/TMDBMovieApp/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct ContentView: View {
11 | var body: some View {
12 | VStack {
13 | Image(systemName: "globe")
14 | .imageScale(.large)
15 | .foregroundStyle(.tint)
16 | Text("Hello, world!")
17 | }
18 | .padding()
19 | }
20 | }
21 |
22 | #Preview {
23 | ContentView()
24 | }
25 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Screens/MovieDetail/CastModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CastModel.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 18/04/24.
6 | //
7 |
8 | import Foundation
9 |
10 | struct CastResponseModel: Decodable {
11 | let cast: [CastModel]
12 | }
13 |
14 | struct CastModel: Decodable, Identifiable {
15 | var id = UUID()
16 | let name, character: String
17 | let imageURL: String?
18 |
19 | enum CodingKeys: String, CodingKey {
20 | case name, character
21 | case imageURL = "profile_path"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/TMDBMovieApp/API/EndPointType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EndPointType.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import Foundation
9 |
10 | enum HTTPMethod: String {
11 | case get = "GET"
12 | case post = "POST"
13 | case patch = "PATCH"
14 | case delete = "DELETE"
15 | }
16 |
17 | protocol EndPointType {
18 | var url: URL? { get }
19 | var path: String { get }
20 | var baseURL: String { get }
21 | var body: Encodable? { get }
22 | var headers: [String: String]? { get }
23 | var method: HTTPMethod { get }
24 | }
25 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Screens/MovieDetail/MovieDetailsViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MovieDetailsViewModel.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 18/04/24.
6 | //
7 |
8 | import Foundation
9 |
10 | @Observable class MovieDetailsViewModel {
11 |
12 | var casts: [CastModel] = []
13 | private let manager = APIManager()
14 |
15 | func loadCasts(id: Int) async {
16 | do {
17 | let response: CastResponseModel = try await manager.request(type: MovieEndPoint.credits(movieID: id))
18 | self.casts = Array(response.cast.prefix(10))
19 | }catch {
20 | print(error)
21 | }
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/TMDBMovieApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "pins" : [
3 | {
4 | "identity" : "kingfisher",
5 | "kind" : "remoteSourceControl",
6 | "location" : "https://github.com/onevcat/Kingfisher.git",
7 | "state" : {
8 | "revision" : "5b92f029fab2cce44386d28588098b5be0824ef5",
9 | "version" : "7.11.0"
10 | }
11 | },
12 | {
13 | "identity" : "swiftui-shimmer",
14 | "kind" : "remoteSourceControl",
15 | "location" : "https://github.com/markiv/SwiftUI-Shimmer",
16 | "state" : {
17 | "revision" : "5659a623567cefe258d1e3e67cb65585fbb6ecb6",
18 | "version" : "1.4.2"
19 | }
20 | }
21 | ],
22 | "version" : 2
23 | }
24 |
--------------------------------------------------------------------------------
/TMDBMovieApp/API/HomeRowView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomeRowView.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import SwiftUI
9 | import Kingfisher
10 |
11 | struct HomeRowView: View {
12 | let movie: Movie
13 |
14 | var body: some View {
15 | VStack {
16 | KFImage(movie.backdropPath?.imageURL)
17 | .resizable()
18 | .scaledToFill()
19 | .scaleEffect(1.1)
20 | .frame(width: 120, height: 150)
21 | .clipShape(RoundedRectangle(cornerRadius: 8))
22 | .clipped()
23 | Text(movie.originalTitle)
24 | .font(.headline)
25 | .lineLimit(2)
26 | .frame(width: 130)
27 | .multilineTextAlignment(.center)
28 | Spacer()
29 | }
30 | }
31 |
32 | }
33 |
34 | #Preview {
35 | HomeRowView(movie: .dummy)
36 | }
37 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Screens/Search/MovieSearchViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MovieSearchViewModel.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 19/04/24.
6 | //
7 |
8 | import Foundation
9 |
10 | @Observable class MovieSearchViewModel {
11 |
12 | var movies: [Movie] = []
13 | private let manager = APIManager()
14 | private var searchTask: Task?
15 |
16 | func searchMovie(by name: String) {
17 | searchTask?.cancel()
18 |
19 | searchTask = Task {
20 | do {
21 | // Simulate debounce by delaying the search task
22 | try await Task.sleep(nanoseconds: 500_000_000) // 0.5 seconds
23 |
24 | let response: MovieResponseModel = try await manager.request(
25 | type: MovieEndPoint.search(name: name)
26 | )
27 | self.movies = response.results
28 | }catch {
29 | print(error)
30 | }
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/TMDBMovieApp.xcodeproj/xcuserdata/yogeshpatel.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SwiftUI Movie App Using TMDB API
2 |
3 | Welcome to the SwiftUI Movie App! This project leverages the TMDB API to display upcoming, top-rated, and popular movies. By clicking on any movie, users can view detailed information including the cast, description, image, title, length, and language.
4 |
5 | 
6 |
7 | ## Features
8 | - **Home Screen:** Browse upcoming, top-rated, and popular movies.
9 | - **Movie Details:** Get comprehensive details about each movie, including cast, description, and more.
10 | - **SwiftUI:** Built entirely with SwiftUI for a smooth and responsive UI.
11 |
12 | ## Installation
13 | 1. Clone the repository:
14 | ```bash
15 | git clone https://github.com/YogeshPateliOS/TMDBMovieApp.git
16 | 2. Navigate to the project directory and open it with Xcode.
17 | 3. Create an API key from the [TMDB Documentation](https://developer.themoviedb.org/reference/intro/getting-started).
18 | 4. Add your TMDB API key to the API key property in the MovieEndPoint file
19 | 5. Build and run the app on your simulator or device.
20 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Screens/Home/MovieView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MovieView.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 16/04/24.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct MovieView: View {
11 |
12 | var title: String
13 | var movies: [Movie]
14 |
15 | var body: some View {
16 | VStack(alignment: .leading) {
17 | Text(title)
18 | .font(.title2)
19 | .fontWeight(.bold)
20 |
21 | popularView
22 | }
23 | }
24 |
25 | var popularView: some View {
26 | ScrollView(.horizontal, showsIndicators: false) {
27 | LazyHStack(alignment: .top) {
28 | ForEach(movies) { movie in
29 | NavigationLink(destination: MovieDetailsView(movie: movie)) {
30 | HomeRowView(movie: movie)
31 | .foregroundColor(.primary)
32 | }
33 | }
34 | }.frame(maxHeight: 200)
35 | }
36 | }
37 | }
38 |
39 | #Preview {
40 | MovieView(title: "Populars", movies: [.dummy])
41 | }
42 |
--------------------------------------------------------------------------------
/TMDBMovieApp/API/APIManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // APIManager.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import Foundation
9 |
10 | enum NetworkError: Error {
11 | case invalidURL
12 | case invalidResponse
13 | case network(_ error: Error?)
14 | case invalidError
15 | }
16 |
17 | final class APIManager {
18 |
19 | func request(type: EndPointType) async throws -> T {
20 | guard let url = type.url else { throw NetworkError.invalidURL }
21 |
22 | var request = URLRequest(url: url)
23 | request.httpMethod = type.method.rawValue
24 |
25 | if let body = type.body {
26 | request.httpBody = try? JSONEncoder().encode(body)
27 | }
28 |
29 | request.allHTTPHeaderFields = type.headers
30 | let (data, response) = try await URLSession.shared.data(for: request)
31 |
32 | guard (response as? HTTPURLResponse)?.statusCode == 200 else { throw NetworkError.invalidResponse }
33 |
34 | return try JSONDecoder().decode(T.self, from: data)
35 | }
36 |
37 | static var commonHeaders: [String: String]? {
38 | ["accept" : "application/json"]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Screens/Home/HomeView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomeView.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import SwiftUI
9 | import Shimmer
10 |
11 | struct HomeView: View {
12 | @State var viewModel = HomeViewModel()
13 |
14 | var body: some View {
15 | NavigationStack {
16 | VStack(alignment: .leading) {
17 | headerView
18 |
19 | ScrollView(showsIndicators: false) {
20 | VStack(spacing: 8) {
21 | MovieView(title: "Upcomings", movies: viewModel.upcomingMovies)
22 |
23 | MovieView(title: "Populars", movies: viewModel.populars)
24 |
25 | MovieView(title: "Top Rated", movies: viewModel.topRatedMovies)
26 | }
27 | }
28 |
29 | Spacer()
30 | }
31 | .padding()
32 | .ignoresSafeArea(edges: .bottom)
33 | .task {
34 | await viewModel.loadMovies()
35 | }
36 | }
37 | }
38 |
39 | var headerView: some View {
40 | VStack(alignment: .leading) {
41 | Text("Welcome back")
42 | .foregroundStyle(.secondary)
43 | .font(.caption)
44 | Text("Yogesh Patel")
45 | .font(.title)
46 | }
47 | }
48 |
49 | }
50 |
51 | #Preview {
52 | HomeView().preferredColorScheme(.dark)
53 | }
54 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Screens/Search/MovieSearchView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MovieSearchView.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 19/04/24.
6 | //
7 |
8 | import SwiftUI
9 | import Kingfisher
10 |
11 | struct MovieSearchView: View {
12 |
13 | @State var viewModel = MovieSearchViewModel()
14 | @State var searchText: String = ""
15 | private let columns = [
16 | GridItem(.flexible(), spacing: 8),
17 | GridItem(.flexible(), spacing: 8),
18 | GridItem(.flexible(), spacing: 8)
19 | ]
20 |
21 | var body: some View {
22 | NavigationStack {
23 | ScrollView {
24 | LazyVGrid(columns: columns, spacing: 4) {
25 | ForEach(viewModel.movies) { movie in
26 | NavigationLink(destination: MovieDetailsView(movie: movie)) {
27 | HomeRowView(movie: movie)
28 | .foregroundColor(.primary)
29 | }
30 | }
31 | }.padding(8)
32 | }
33 | }
34 | .searchable(text: $searchText, prompt: "Search movie by name")
35 | .onChange(of: searchText) { _, newValue in
36 | if newValue.isEmpty {
37 | viewModel.movies.removeAll()
38 | }else {
39 | viewModel.searchMovie(by: newValue)
40 | }
41 | }
42 | }
43 | }
44 |
45 | #Preview {
46 | MovieSearchView()
47 | }
48 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Screens/Home/HomeViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomeViewModel.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import Foundation
9 |
10 | @Observable class HomeViewModel {
11 |
12 | var populars: [Movie] = []
13 | var topRatedMovies: [Movie] = []
14 | var upcomingMovies: [Movie] = []
15 | private let apiManager = APIManager()
16 |
17 | func loadMovies() async {
18 | await withTaskGroup(of: Void.self) { group in
19 | group.addTask { await self.loadPopularMovies() }
20 | group.addTask { await self.loadTopRatedMovies() }
21 | group.addTask { await self.loadUpcomingMovies() }
22 | }
23 | }
24 |
25 | private func loadPopularMovies() async {
26 | do {
27 | let response: MovieResponseModel = try await apiManager.request(type: MovieEndPoint.popular)
28 | self.populars = response.results
29 | }catch {
30 | print(error)
31 | }
32 | }
33 |
34 | private func loadTopRatedMovies() async {
35 | do {
36 | let response: MovieResponseModel = try await apiManager.request(type: MovieEndPoint.topRated)
37 | self.topRatedMovies = response.results
38 | }catch {
39 | print(error)
40 | }
41 | }
42 |
43 | private func loadUpcomingMovies() async {
44 | do {
45 | let response: MovieResponseModel = try await apiManager.request(type: MovieEndPoint.upcoming)
46 | self.upcomingMovies = response.results
47 | }catch {
48 | print(error)
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/TMDBMovieApp/API/MovieEndPoint.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MovieEndPoint.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import Foundation
9 |
10 | enum MovieEndPoint {
11 | case popular
12 | case topRated
13 | case upcoming
14 | case credits(movieID: Int)
15 | case search(name: String)
16 | }
17 |
18 | extension MovieEndPoint: EndPointType {
19 |
20 | private var apiKey: String {
21 | "ADD_YOUR_API_KEY"
22 | }
23 |
24 | var url: URL? {
25 | switch self {
26 | case .search:
27 | URL(string: baseURL + path + "&api_key=\(apiKey)")
28 | default:
29 | URL(string: baseURL + path + "?api_key=\(apiKey)")
30 | }
31 | }
32 |
33 | var path: String {
34 | switch self {
35 | case .popular:
36 | return "popular"
37 | case .topRated:
38 | return "top_rated"
39 | case .upcoming:
40 | return "upcoming"
41 | case .credits(let id):
42 | return "\(id)" + "/credits"
43 | case .search(let name):
44 | return "query=\(name)"
45 | }
46 | }
47 |
48 | var baseURL: String {
49 | switch self {
50 | case .search:
51 | return "https://api.themoviedb.org/3/search/movie?"
52 | default:
53 | return "https://api.themoviedb.org/3/movie/"
54 | }
55 | }
56 |
57 | var body: Encodable? {
58 | nil
59 | }
60 |
61 | var headers: [String : String]? {
62 | APIManager.commonHeaders
63 | }
64 |
65 | var method: HTTPMethod {
66 | .get
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/TMDBMovieApp/API/MovieModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MovieModel.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 15/04/24.
6 | //
7 |
8 | import Foundation
9 |
10 | struct MovieResponseModel: Decodable {
11 | let results: [Movie]
12 | }
13 |
14 | struct Movie: Decodable, Identifiable, Hashable {
15 | let id: Int
16 | let originalTitle, overview: String
17 | let posterPath: String?
18 | let releaseDate, title: String
19 | let backdropPath: String?
20 | let popularity, voteAverage: Double
21 | let voteCount: Int
22 |
23 | enum CodingKeys: String, CodingKey {
24 | case id
25 | case originalTitle = "original_title"
26 | case overview
27 | case posterPath = "poster_path"
28 | case popularity
29 | case releaseDate = "release_date"
30 | case title
31 | case voteAverage = "vote_average"
32 | case voteCount = "vote_count"
33 | case backdropPath = "backdrop_path"
34 | }
35 | }
36 |
37 | extension Movie {
38 |
39 | static var dummy: Movie {
40 | .init(id: 693134,
41 | originalTitle: "Dune: Part Two",
42 | overview: "Follow the mythic journey of Paul Atreides as he unites with Chani and the Fremen while on a path of revenge against the conspirators who destroyed his family. Facing a choice between the love of his life and the fate of the known universe, Paul endeavors to prevent a terrible future only he can foresee.",
43 | posterPath: "/1pdfLvkbY9ohJlCjQH2CZjjYVvJ.jpg",
44 | releaseDate: "2024-02-27",
45 | title: "Dune: Part Two",
46 | backdropPath: "/xOMo8BRK7PfcJv9JCnx7s5hj0PX.jpg",
47 | popularity: 4661.985,
48 | voteAverage: 8.309,
49 | voteCount: 2827)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/TMDBMovieApp/Screens/MovieDetail/MovieDetailsView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MovieDetailsView.swift
3 | // TMDBMovieApp
4 | //
5 | // Created by Yogesh Patel on 16/04/24.
6 | //
7 |
8 | import SwiftUI
9 | import Kingfisher
10 |
11 | struct MovieDetailsView: View {
12 | @State var viewModel = MovieDetailsViewModel()
13 | let movie: Movie
14 |
15 | var body: some View {
16 | GeometryReader { geometry in
17 | VStack(spacing: 0) {
18 | ZStack {
19 | KFImage(movie.backdropPath?.imageURL)
20 | .resizable()
21 | .aspectRatio(contentMode: .fill)
22 | .frame(
23 | width: geometry.size.width,
24 | height: geometry.size.height * 0.4
25 | )
26 | .clipped()
27 |
28 | VStack {
29 | Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: {
30 | VStack(spacing: 8) {
31 | Image(systemName: "play.circle")
32 | .resizable()
33 | .fontWeight(.light)
34 | .frame(width: 80, height: 80, alignment: .center)
35 | .foregroundColor(.white)
36 | Text("Play trailer")
37 | .foregroundStyle(.white)
38 | .font(.headline)
39 | }
40 | })
41 |
42 | }
43 |
44 | }
45 |
46 | Spacer()
47 |
48 | ScrollView(showsIndicators: false) {
49 | VStack(alignment: .leading, spacing: 16) {
50 | Text(movie.originalTitle)
51 | .font(.title)
52 |
53 | HStack(spacing: 16) {
54 | Text("18+")
55 | .font(.caption)
56 | .padding(8)
57 | .padding(.horizontal, 8)
58 | .background(Capsule().stroke())
59 |
60 | HStack(spacing: 16) {
61 | Text("3h 12m")
62 | .font(.subheadline)
63 |
64 | Image(systemName: "circle.fill")
65 | .resizable()
66 | .frame(width: 5, height: 5)
67 |
68 | Text(movie.releaseDate)
69 | .font(.subheadline)
70 | }
71 | .foregroundStyle(.secondary)
72 |
73 | Spacer()
74 | }
75 |
76 | HStack(spacing: 8) {
77 | VStack(spacing: 5) {
78 | Image(systemName: "square.and.arrow.down")
79 | Text("Download")
80 | .font(.footnote)
81 | }
82 |
83 | Spacer()
84 |
85 | Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: {
86 | Text("Play Now")
87 | .frame(height: 44)
88 | .frame(maxWidth: .infinity)
89 | .tint(.white)
90 | .font(.headline)
91 | .background(.blue)
92 | .clipShape(.capsule)
93 | })
94 | }
95 |
96 | Text(movie.overview)
97 | .foregroundStyle(.secondary)
98 | .font(.callout)
99 | .lineLimit(4)
100 |
101 | Spacer()
102 |
103 | Text("Cast")
104 | .font(.title3)
105 | ScrollView(.horizontal, showsIndicators: false, content: {
106 | LazyHStack(alignment: .top,content: {
107 | ForEach(viewModel.casts) { cast in
108 | VStack {
109 | KFImage(cast.imageURL?.imageURL)
110 | .resizable()
111 | .scaledToFit()
112 | .scaleEffect(1)
113 | .frame(width: 80, height: 80)
114 | .clipShape(RoundedRectangle(cornerRadius: 8))
115 | .clipped()
116 | Text(cast.name)
117 | }
118 | .frame(width: 80)
119 | }
120 | })
121 | })
122 |
123 | Spacer()
124 | }
125 | .padding()
126 | .frame(
127 | width: geometry.size.width,
128 | height: geometry.size.height * 0.6
129 | )
130 | }
131 | }
132 | .task {
133 | await viewModel.loadCasts(id: movie.id)
134 | }
135 | }
136 | .ignoresSafeArea()
137 | }
138 | }
139 |
140 | #Preview {
141 | MovieDetailsView(movie: .dummy)
142 | }
143 |
--------------------------------------------------------------------------------
/TMDBMovieApp.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 56;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 906192912BD21275007D8EE1 /* MovieDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 906192902BD21275007D8EE1 /* MovieDetailsViewModel.swift */; };
11 | 906192932BD212A9007D8EE1 /* CastModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 906192922BD212A9007D8EE1 /* CastModel.swift */; };
12 | 9061F9192BCF4B4F00A6A90E /* Shimmer in Frameworks */ = {isa = PBXBuildFile; productRef = 9061F9182BCF4B4F00A6A90E /* Shimmer */; };
13 | 9061F91B2BCF4CE900A6A90E /* MovieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9061F91A2BCF4CE900A6A90E /* MovieView.swift */; };
14 | 9061F91E2BCF51E700A6A90E /* MovieDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9061F91D2BCF51E700A6A90E /* MovieDetailsView.swift */; };
15 | 90793FB52BCE0F0100E6A2D1 /* TMDBMovieAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FB42BCE0F0100E6A2D1 /* TMDBMovieAppApp.swift */; };
16 | 90793FB72BCE0F0100E6A2D1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FB62BCE0F0100E6A2D1 /* ContentView.swift */; };
17 | 90793FB92BCE0F0300E6A2D1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 90793FB82BCE0F0300E6A2D1 /* Assets.xcassets */; };
18 | 90793FBC2BCE0F0300E6A2D1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 90793FBB2BCE0F0300E6A2D1 /* Preview Assets.xcassets */; };
19 | 90793FC52BCE105100E6A2D1 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FC42BCE105100E6A2D1 /* HomeView.swift */; };
20 | 90793FC72BCE108700E6A2D1 /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FC62BCE108700E6A2D1 /* HomeViewModel.swift */; };
21 | 90793FCA2BCE167600E6A2D1 /* APIManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FC92BCE167600E6A2D1 /* APIManager.swift */; };
22 | 90793FCC2BCE16A100E6A2D1 /* EndPointType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FCB2BCE16A100E6A2D1 /* EndPointType.swift */; };
23 | 90793FCE2BCE16B200E6A2D1 /* MovieEndPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FCD2BCE16B200E6A2D1 /* MovieEndPoint.swift */; };
24 | 90793FD02BCE185900E6A2D1 /* MovieModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FCF2BCE185900E6A2D1 /* MovieModel.swift */; };
25 | 90793FD32BCE1F2700E6A2D1 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 90793FD22BCE1F2700E6A2D1 /* Kingfisher */; };
26 | 90793FD52BCE1F4D00E6A2D1 /* HomeRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FD42BCE1F4D00E6A2D1 /* HomeRowView.swift */; };
27 | 90793FD72BCE1FD900E6A2D1 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90793FD62BCE1FD900E6A2D1 /* String+Extension.swift */; };
28 | 90B4D8222BD32CDF000A2741 /* MovieSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90B4D8212BD32CDF000A2741 /* MovieSearchView.swift */; };
29 | 90B4D8242BD32F5D000A2741 /* MovieSearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90B4D8232BD32F5D000A2741 /* MovieSearchViewModel.swift */; };
30 | /* End PBXBuildFile section */
31 |
32 | /* Begin PBXFileReference section */
33 | 906192902BD21275007D8EE1 /* MovieDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieDetailsViewModel.swift; sourceTree = ""; };
34 | 906192922BD212A9007D8EE1 /* CastModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CastModel.swift; sourceTree = ""; };
35 | 9061F91A2BCF4CE900A6A90E /* MovieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieView.swift; sourceTree = ""; };
36 | 9061F91D2BCF51E700A6A90E /* MovieDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieDetailsView.swift; sourceTree = ""; };
37 | 90793FB12BCE0F0100E6A2D1 /* TMDBMovieApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TMDBMovieApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
38 | 90793FB42BCE0F0100E6A2D1 /* TMDBMovieAppApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TMDBMovieAppApp.swift; sourceTree = ""; };
39 | 90793FB62BCE0F0100E6A2D1 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
40 | 90793FB82BCE0F0300E6A2D1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
41 | 90793FBB2BCE0F0300E6A2D1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
42 | 90793FC42BCE105100E6A2D1 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; };
43 | 90793FC62BCE108700E6A2D1 /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = ""; };
44 | 90793FC92BCE167600E6A2D1 /* APIManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIManager.swift; sourceTree = ""; };
45 | 90793FCB2BCE16A100E6A2D1 /* EndPointType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndPointType.swift; sourceTree = ""; };
46 | 90793FCD2BCE16B200E6A2D1 /* MovieEndPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieEndPoint.swift; sourceTree = ""; };
47 | 90793FCF2BCE185900E6A2D1 /* MovieModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieModel.swift; sourceTree = ""; };
48 | 90793FD42BCE1F4D00E6A2D1 /* HomeRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeRowView.swift; sourceTree = ""; };
49 | 90793FD62BCE1FD900E6A2D1 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = ""; };
50 | 90B4D8212BD32CDF000A2741 /* MovieSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchView.swift; sourceTree = ""; };
51 | 90B4D8232BD32F5D000A2741 /* MovieSearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchViewModel.swift; sourceTree = ""; };
52 | /* End PBXFileReference section */
53 |
54 | /* Begin PBXFrameworksBuildPhase section */
55 | 90793FAE2BCE0F0100E6A2D1 /* Frameworks */ = {
56 | isa = PBXFrameworksBuildPhase;
57 | buildActionMask = 2147483647;
58 | files = (
59 | 9061F9192BCF4B4F00A6A90E /* Shimmer in Frameworks */,
60 | 90793FD32BCE1F2700E6A2D1 /* Kingfisher in Frameworks */,
61 | );
62 | runOnlyForDeploymentPostprocessing = 0;
63 | };
64 | /* End PBXFrameworksBuildPhase section */
65 |
66 | /* Begin PBXGroup section */
67 | 9061F91C2BCF51D800A6A90E /* MovieDetail */ = {
68 | isa = PBXGroup;
69 | children = (
70 | 9061F91D2BCF51E700A6A90E /* MovieDetailsView.swift */,
71 | 906192902BD21275007D8EE1 /* MovieDetailsViewModel.swift */,
72 | 906192922BD212A9007D8EE1 /* CastModel.swift */,
73 | );
74 | path = MovieDetail;
75 | sourceTree = "";
76 | };
77 | 90793FA82BCE0F0100E6A2D1 = {
78 | isa = PBXGroup;
79 | children = (
80 | 90793FB32BCE0F0100E6A2D1 /* TMDBMovieApp */,
81 | 90793FB22BCE0F0100E6A2D1 /* Products */,
82 | );
83 | sourceTree = "";
84 | };
85 | 90793FB22BCE0F0100E6A2D1 /* Products */ = {
86 | isa = PBXGroup;
87 | children = (
88 | 90793FB12BCE0F0100E6A2D1 /* TMDBMovieApp.app */,
89 | );
90 | name = Products;
91 | sourceTree = "";
92 | };
93 | 90793FB32BCE0F0100E6A2D1 /* TMDBMovieApp */ = {
94 | isa = PBXGroup;
95 | children = (
96 | 90793FC82BCE166F00E6A2D1 /* API */,
97 | 90793FC22BCE0F1100E6A2D1 /* Screens */,
98 | 90793FB42BCE0F0100E6A2D1 /* TMDBMovieAppApp.swift */,
99 | 90793FB62BCE0F0100E6A2D1 /* ContentView.swift */,
100 | 90793FB82BCE0F0300E6A2D1 /* Assets.xcassets */,
101 | 90793FBA2BCE0F0300E6A2D1 /* Preview Content */,
102 | 90793FD62BCE1FD900E6A2D1 /* String+Extension.swift */,
103 | );
104 | path = TMDBMovieApp;
105 | sourceTree = "";
106 | };
107 | 90793FBA2BCE0F0300E6A2D1 /* Preview Content */ = {
108 | isa = PBXGroup;
109 | children = (
110 | 90793FBB2BCE0F0300E6A2D1 /* Preview Assets.xcassets */,
111 | );
112 | path = "Preview Content";
113 | sourceTree = "";
114 | };
115 | 90793FC22BCE0F1100E6A2D1 /* Screens */ = {
116 | isa = PBXGroup;
117 | children = (
118 | 90B4D8202BD32CD0000A2741 /* Search */,
119 | 90793FC32BCE0F1700E6A2D1 /* Home */,
120 | 9061F91C2BCF51D800A6A90E /* MovieDetail */,
121 | );
122 | path = Screens;
123 | sourceTree = "";
124 | };
125 | 90793FC32BCE0F1700E6A2D1 /* Home */ = {
126 | isa = PBXGroup;
127 | children = (
128 | 90793FC42BCE105100E6A2D1 /* HomeView.swift */,
129 | 90793FC62BCE108700E6A2D1 /* HomeViewModel.swift */,
130 | 9061F91A2BCF4CE900A6A90E /* MovieView.swift */,
131 | );
132 | path = Home;
133 | sourceTree = "";
134 | };
135 | 90793FC82BCE166F00E6A2D1 /* API */ = {
136 | isa = PBXGroup;
137 | children = (
138 | 90793FC92BCE167600E6A2D1 /* APIManager.swift */,
139 | 90793FCB2BCE16A100E6A2D1 /* EndPointType.swift */,
140 | 90793FCD2BCE16B200E6A2D1 /* MovieEndPoint.swift */,
141 | 90793FCF2BCE185900E6A2D1 /* MovieModel.swift */,
142 | 90793FD42BCE1F4D00E6A2D1 /* HomeRowView.swift */,
143 | );
144 | path = API;
145 | sourceTree = "";
146 | };
147 | 90B4D8202BD32CD0000A2741 /* Search */ = {
148 | isa = PBXGroup;
149 | children = (
150 | 90B4D8212BD32CDF000A2741 /* MovieSearchView.swift */,
151 | 90B4D8232BD32F5D000A2741 /* MovieSearchViewModel.swift */,
152 | );
153 | path = Search;
154 | sourceTree = "";
155 | };
156 | /* End PBXGroup section */
157 |
158 | /* Begin PBXNativeTarget section */
159 | 90793FB02BCE0F0100E6A2D1 /* TMDBMovieApp */ = {
160 | isa = PBXNativeTarget;
161 | buildConfigurationList = 90793FBF2BCE0F0300E6A2D1 /* Build configuration list for PBXNativeTarget "TMDBMovieApp" */;
162 | buildPhases = (
163 | 90793FAD2BCE0F0100E6A2D1 /* Sources */,
164 | 90793FAE2BCE0F0100E6A2D1 /* Frameworks */,
165 | 90793FAF2BCE0F0100E6A2D1 /* Resources */,
166 | );
167 | buildRules = (
168 | );
169 | dependencies = (
170 | );
171 | name = TMDBMovieApp;
172 | packageProductDependencies = (
173 | 90793FD22BCE1F2700E6A2D1 /* Kingfisher */,
174 | 9061F9182BCF4B4F00A6A90E /* Shimmer */,
175 | );
176 | productName = TMDBMovieApp;
177 | productReference = 90793FB12BCE0F0100E6A2D1 /* TMDBMovieApp.app */;
178 | productType = "com.apple.product-type.application";
179 | };
180 | /* End PBXNativeTarget section */
181 |
182 | /* Begin PBXProject section */
183 | 90793FA92BCE0F0100E6A2D1 /* Project object */ = {
184 | isa = PBXProject;
185 | attributes = {
186 | BuildIndependentTargetsInParallel = 1;
187 | LastSwiftUpdateCheck = 1500;
188 | LastUpgradeCheck = 1500;
189 | TargetAttributes = {
190 | 90793FB02BCE0F0100E6A2D1 = {
191 | CreatedOnToolsVersion = 15.0;
192 | };
193 | };
194 | };
195 | buildConfigurationList = 90793FAC2BCE0F0100E6A2D1 /* Build configuration list for PBXProject "TMDBMovieApp" */;
196 | compatibilityVersion = "Xcode 14.0";
197 | developmentRegion = en;
198 | hasScannedForEncodings = 0;
199 | knownRegions = (
200 | en,
201 | Base,
202 | );
203 | mainGroup = 90793FA82BCE0F0100E6A2D1;
204 | packageReferences = (
205 | 90793FD12BCE1F2700E6A2D1 /* XCRemoteSwiftPackageReference "Kingfisher" */,
206 | 9061F9172BCF4B4F00A6A90E /* XCRemoteSwiftPackageReference "SwiftUI-Shimmer" */,
207 | );
208 | productRefGroup = 90793FB22BCE0F0100E6A2D1 /* Products */;
209 | projectDirPath = "";
210 | projectRoot = "";
211 | targets = (
212 | 90793FB02BCE0F0100E6A2D1 /* TMDBMovieApp */,
213 | );
214 | };
215 | /* End PBXProject section */
216 |
217 | /* Begin PBXResourcesBuildPhase section */
218 | 90793FAF2BCE0F0100E6A2D1 /* Resources */ = {
219 | isa = PBXResourcesBuildPhase;
220 | buildActionMask = 2147483647;
221 | files = (
222 | 90793FBC2BCE0F0300E6A2D1 /* Preview Assets.xcassets in Resources */,
223 | 90793FB92BCE0F0300E6A2D1 /* Assets.xcassets in Resources */,
224 | );
225 | runOnlyForDeploymentPostprocessing = 0;
226 | };
227 | /* End PBXResourcesBuildPhase section */
228 |
229 | /* Begin PBXSourcesBuildPhase section */
230 | 90793FAD2BCE0F0100E6A2D1 /* Sources */ = {
231 | isa = PBXSourcesBuildPhase;
232 | buildActionMask = 2147483647;
233 | files = (
234 | 90B4D8222BD32CDF000A2741 /* MovieSearchView.swift in Sources */,
235 | 90793FC52BCE105100E6A2D1 /* HomeView.swift in Sources */,
236 | 90793FB72BCE0F0100E6A2D1 /* ContentView.swift in Sources */,
237 | 90793FCC2BCE16A100E6A2D1 /* EndPointType.swift in Sources */,
238 | 90793FCA2BCE167600E6A2D1 /* APIManager.swift in Sources */,
239 | 90793FD02BCE185900E6A2D1 /* MovieModel.swift in Sources */,
240 | 90793FD52BCE1F4D00E6A2D1 /* HomeRowView.swift in Sources */,
241 | 90B4D8242BD32F5D000A2741 /* MovieSearchViewModel.swift in Sources */,
242 | 9061F91E2BCF51E700A6A90E /* MovieDetailsView.swift in Sources */,
243 | 90793FCE2BCE16B200E6A2D1 /* MovieEndPoint.swift in Sources */,
244 | 906192932BD212A9007D8EE1 /* CastModel.swift in Sources */,
245 | 906192912BD21275007D8EE1 /* MovieDetailsViewModel.swift in Sources */,
246 | 90793FB52BCE0F0100E6A2D1 /* TMDBMovieAppApp.swift in Sources */,
247 | 90793FD72BCE1FD900E6A2D1 /* String+Extension.swift in Sources */,
248 | 90793FC72BCE108700E6A2D1 /* HomeViewModel.swift in Sources */,
249 | 9061F91B2BCF4CE900A6A90E /* MovieView.swift in Sources */,
250 | );
251 | runOnlyForDeploymentPostprocessing = 0;
252 | };
253 | /* End PBXSourcesBuildPhase section */
254 |
255 | /* Begin XCBuildConfiguration section */
256 | 90793FBD2BCE0F0300E6A2D1 /* Debug */ = {
257 | isa = XCBuildConfiguration;
258 | buildSettings = {
259 | ALWAYS_SEARCH_USER_PATHS = NO;
260 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
261 | CLANG_ANALYZER_NONNULL = YES;
262 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
263 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
264 | CLANG_ENABLE_MODULES = YES;
265 | CLANG_ENABLE_OBJC_ARC = YES;
266 | CLANG_ENABLE_OBJC_WEAK = YES;
267 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
268 | CLANG_WARN_BOOL_CONVERSION = YES;
269 | CLANG_WARN_COMMA = YES;
270 | CLANG_WARN_CONSTANT_CONVERSION = YES;
271 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
272 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
273 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
274 | CLANG_WARN_EMPTY_BODY = YES;
275 | CLANG_WARN_ENUM_CONVERSION = YES;
276 | CLANG_WARN_INFINITE_RECURSION = YES;
277 | CLANG_WARN_INT_CONVERSION = YES;
278 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
279 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
280 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
281 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
282 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
283 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
284 | CLANG_WARN_STRICT_PROTOTYPES = YES;
285 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
286 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
287 | CLANG_WARN_UNREACHABLE_CODE = YES;
288 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
289 | COPY_PHASE_STRIP = NO;
290 | DEBUG_INFORMATION_FORMAT = dwarf;
291 | ENABLE_STRICT_OBJC_MSGSEND = YES;
292 | ENABLE_TESTABILITY = YES;
293 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
294 | GCC_C_LANGUAGE_STANDARD = gnu17;
295 | GCC_DYNAMIC_NO_PIC = NO;
296 | GCC_NO_COMMON_BLOCKS = YES;
297 | GCC_OPTIMIZATION_LEVEL = 0;
298 | GCC_PREPROCESSOR_DEFINITIONS = (
299 | "DEBUG=1",
300 | "$(inherited)",
301 | );
302 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
303 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
304 | GCC_WARN_UNDECLARED_SELECTOR = YES;
305 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
306 | GCC_WARN_UNUSED_FUNCTION = YES;
307 | GCC_WARN_UNUSED_VARIABLE = YES;
308 | IPHONEOS_DEPLOYMENT_TARGET = 17.0;
309 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
310 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
311 | MTL_FAST_MATH = YES;
312 | ONLY_ACTIVE_ARCH = YES;
313 | SDKROOT = iphoneos;
314 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
315 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
316 | };
317 | name = Debug;
318 | };
319 | 90793FBE2BCE0F0300E6A2D1 /* Release */ = {
320 | isa = XCBuildConfiguration;
321 | buildSettings = {
322 | ALWAYS_SEARCH_USER_PATHS = NO;
323 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
324 | CLANG_ANALYZER_NONNULL = YES;
325 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
326 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
327 | CLANG_ENABLE_MODULES = YES;
328 | CLANG_ENABLE_OBJC_ARC = YES;
329 | CLANG_ENABLE_OBJC_WEAK = YES;
330 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
331 | CLANG_WARN_BOOL_CONVERSION = YES;
332 | CLANG_WARN_COMMA = YES;
333 | CLANG_WARN_CONSTANT_CONVERSION = YES;
334 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
335 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
336 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
337 | CLANG_WARN_EMPTY_BODY = YES;
338 | CLANG_WARN_ENUM_CONVERSION = YES;
339 | CLANG_WARN_INFINITE_RECURSION = YES;
340 | CLANG_WARN_INT_CONVERSION = YES;
341 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
342 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
343 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
344 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
345 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
346 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
347 | CLANG_WARN_STRICT_PROTOTYPES = YES;
348 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
349 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
350 | CLANG_WARN_UNREACHABLE_CODE = YES;
351 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
352 | COPY_PHASE_STRIP = NO;
353 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
354 | ENABLE_NS_ASSERTIONS = NO;
355 | ENABLE_STRICT_OBJC_MSGSEND = YES;
356 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
357 | GCC_C_LANGUAGE_STANDARD = gnu17;
358 | GCC_NO_COMMON_BLOCKS = YES;
359 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
360 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
361 | GCC_WARN_UNDECLARED_SELECTOR = YES;
362 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
363 | GCC_WARN_UNUSED_FUNCTION = YES;
364 | GCC_WARN_UNUSED_VARIABLE = YES;
365 | IPHONEOS_DEPLOYMENT_TARGET = 17.0;
366 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
367 | MTL_ENABLE_DEBUG_INFO = NO;
368 | MTL_FAST_MATH = YES;
369 | SDKROOT = iphoneos;
370 | SWIFT_COMPILATION_MODE = wholemodule;
371 | VALIDATE_PRODUCT = YES;
372 | };
373 | name = Release;
374 | };
375 | 90793FC02BCE0F0300E6A2D1 /* Debug */ = {
376 | isa = XCBuildConfiguration;
377 | buildSettings = {
378 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
379 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
380 | CODE_SIGN_STYLE = Automatic;
381 | CURRENT_PROJECT_VERSION = 1;
382 | DEVELOPMENT_ASSET_PATHS = "\"TMDBMovieApp/Preview Content\"";
383 | DEVELOPMENT_TEAM = CF4QM4CNHN;
384 | ENABLE_PREVIEWS = YES;
385 | GENERATE_INFOPLIST_FILE = YES;
386 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
387 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
388 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
389 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
390 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
391 | LD_RUNPATH_SEARCH_PATHS = (
392 | "$(inherited)",
393 | "@executable_path/Frameworks",
394 | );
395 | MARKETING_VERSION = 1.0;
396 | PRODUCT_BUNDLE_IDENTIFIER = com.yogeshpatel.TMDBMovieApp;
397 | PRODUCT_NAME = "$(TARGET_NAME)";
398 | SWIFT_EMIT_LOC_STRINGS = YES;
399 | SWIFT_VERSION = 5.0;
400 | TARGETED_DEVICE_FAMILY = "1,2";
401 | };
402 | name = Debug;
403 | };
404 | 90793FC12BCE0F0300E6A2D1 /* Release */ = {
405 | isa = XCBuildConfiguration;
406 | buildSettings = {
407 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
408 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
409 | CODE_SIGN_STYLE = Automatic;
410 | CURRENT_PROJECT_VERSION = 1;
411 | DEVELOPMENT_ASSET_PATHS = "\"TMDBMovieApp/Preview Content\"";
412 | DEVELOPMENT_TEAM = CF4QM4CNHN;
413 | ENABLE_PREVIEWS = YES;
414 | GENERATE_INFOPLIST_FILE = YES;
415 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
416 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
417 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
418 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
419 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
420 | LD_RUNPATH_SEARCH_PATHS = (
421 | "$(inherited)",
422 | "@executable_path/Frameworks",
423 | );
424 | MARKETING_VERSION = 1.0;
425 | PRODUCT_BUNDLE_IDENTIFIER = com.yogeshpatel.TMDBMovieApp;
426 | PRODUCT_NAME = "$(TARGET_NAME)";
427 | SWIFT_EMIT_LOC_STRINGS = YES;
428 | SWIFT_VERSION = 5.0;
429 | TARGETED_DEVICE_FAMILY = "1,2";
430 | };
431 | name = Release;
432 | };
433 | /* End XCBuildConfiguration section */
434 |
435 | /* Begin XCConfigurationList section */
436 | 90793FAC2BCE0F0100E6A2D1 /* Build configuration list for PBXProject "TMDBMovieApp" */ = {
437 | isa = XCConfigurationList;
438 | buildConfigurations = (
439 | 90793FBD2BCE0F0300E6A2D1 /* Debug */,
440 | 90793FBE2BCE0F0300E6A2D1 /* Release */,
441 | );
442 | defaultConfigurationIsVisible = 0;
443 | defaultConfigurationName = Release;
444 | };
445 | 90793FBF2BCE0F0300E6A2D1 /* Build configuration list for PBXNativeTarget "TMDBMovieApp" */ = {
446 | isa = XCConfigurationList;
447 | buildConfigurations = (
448 | 90793FC02BCE0F0300E6A2D1 /* Debug */,
449 | 90793FC12BCE0F0300E6A2D1 /* Release */,
450 | );
451 | defaultConfigurationIsVisible = 0;
452 | defaultConfigurationName = Release;
453 | };
454 | /* End XCConfigurationList section */
455 |
456 | /* Begin XCRemoteSwiftPackageReference section */
457 | 9061F9172BCF4B4F00A6A90E /* XCRemoteSwiftPackageReference "SwiftUI-Shimmer" */ = {
458 | isa = XCRemoteSwiftPackageReference;
459 | repositoryURL = "https://github.com/markiv/SwiftUI-Shimmer";
460 | requirement = {
461 | kind = upToNextMajorVersion;
462 | minimumVersion = 1.4.2;
463 | };
464 | };
465 | 90793FD12BCE1F2700E6A2D1 /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
466 | isa = XCRemoteSwiftPackageReference;
467 | repositoryURL = "https://github.com/onevcat/Kingfisher.git";
468 | requirement = {
469 | kind = upToNextMajorVersion;
470 | minimumVersion = 7.11.0;
471 | };
472 | };
473 | /* End XCRemoteSwiftPackageReference section */
474 |
475 | /* Begin XCSwiftPackageProductDependency section */
476 | 9061F9182BCF4B4F00A6A90E /* Shimmer */ = {
477 | isa = XCSwiftPackageProductDependency;
478 | package = 9061F9172BCF4B4F00A6A90E /* XCRemoteSwiftPackageReference "SwiftUI-Shimmer" */;
479 | productName = Shimmer;
480 | };
481 | 90793FD22BCE1F2700E6A2D1 /* Kingfisher */ = {
482 | isa = XCSwiftPackageProductDependency;
483 | package = 90793FD12BCE1F2700E6A2D1 /* XCRemoteSwiftPackageReference "Kingfisher" */;
484 | productName = Kingfisher;
485 | };
486 | /* End XCSwiftPackageProductDependency section */
487 | };
488 | rootObject = 90793FA92BCE0F0100E6A2D1 /* Project object */;
489 | }
490 |
--------------------------------------------------------------------------------