How to build a Movie app with Xcode and AI

Team Alex · April 6, 2025

Tutorial

Estimated completion time: 3 min read

How to Build a Movie App with Xcode and AI

Overview

In this tutorial, we're going to build a Movie app using Xcode, Swift, SwiftUI, and The Movie Database (TMDb) API. This app will allow users to browse a list of movies, view detailed information, and save their favorites. We'll also introduce Alex, a helpful AI assistant for Xcode, to demonstrate how AI can help you navigate through the new iOS project seamlessly.

Prerequisites

Implementation Steps

1. Project Setup & Planning

Step 1: Open Xcode and create a new project. Choose "App" under iOS and name the project MovieApp. Make sure to select SwiftUI and Swift.

Step 2: Plan the app structure:

  • Home screen with a list of popular movies
  • Detail screen for each movie
  • Option to favorite movies and store them locally

Step 3: Create a Movie data model manually:

struct Movie: Codable, Identifiable {
    let id: Int
    let title: String
    let overview: String
    let release_date: String
    let poster_path: String?
}

2. Core Features

Step 4: Create a MovieListView with a List in a NavigationView:

struct MovieListView: View {
    @StateObject private var viewModel = MovieViewModel()
 
    var body: some View {
        NavigationView {
            List(viewModel.movies) { movie in
                NavigationLink(destination: MovieDetailView(movie: movie)) {
                    Text(movie.title)
                }
            }
            .navigationTitle("Popular Movies")
        }
        .onAppear {
            viewModel.fetchMovies()
        }
    }
}

Step 5: Create the ViewModel and fetch data from TMDb:

class MovieViewModel: ObservableObject {
    @Published var movies: [Movie] = []
 
    func fetchMovies() {
        guard let url = URL(string: "https://api.themoviedb.org/3/movie/popular?api_key=YOUR_API_KEY") else { return }
 
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode(MovieResponse.self, from: data) {
                    DispatchQueue.main.async {
                        self.movies = decodedResponse.results
                    }
                }
            }
        }.resume()
    }
}
 
struct MovieResponse: Codable {
    let results: [Movie]
}

Step 6: Create a detail view:

struct MovieDetailView: View {
    var movie: Movie
 
    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 16) {
                Text(movie.title).font(.title).bold()
                Text("Released: \(movie.release_date)").font(.subheadline)
                Text(movie.overview).font(.body)
            }
            .padding()
        }
        .navigationTitle("Details")
    }
}

3. Data & Storage

Step 7: Save favorites using UserDefaults:

class FavoritesManager: ObservableObject {
    @Published var favorites: [Movie] = []
 
    func addToFavorites(movie: Movie) {
        if !favorites.contains(where: { $0.id == movie.id }) {
            favorites.append(movie)
            saveFavorites()
        }
    }
 
    func saveFavorites() {
        if let encoded = try? JSONEncoder().encode(favorites) {
            UserDefaults.standard.set(encoded, forKey: "Favorites")
        }
    }
 
    func loadFavorites() {
        if let saved = UserDefaults.standard.data(forKey: "Favorites"),
           let decoded = try? JSONDecoder().decode([Movie].self, from: saved) {
            favorites = decoded
        }
    }
}

4. Polish & Refinement

Step 8: Add loading states:

@Published var isLoading = false
 
func fetchMovies() {
    isLoading = true
    // fetch logic...
    DispatchQueue.main.async {
        self.isLoading = false
    }
}

Step 9: Add animations to transitions or image loading.

Step 10: Test and optimize performance for smooth scrolling and loading.

Now Try Alex

Once your manual structure is complete, you can now invite Alex into your workflow. Try commands like:

  • “Generate SwiftUI view for favorited movies”
  • “Add pull to refresh to MovieListView”
  • “Fix this decoding error”

Alex can handle error fixes, UI generation from sketches, and boilerplate code—all inside Xcode.

Next Steps

Now that you have a working movie app:

  • Add search functionality using TMDb’s search endpoint
  • Add support for genres and filtering
  • Allow offline support

Conclusion

You’ve built a Movie app from scratch using Xcode, SwiftUI, and TMDb API. You also learned how to manually handle core app architecture before introducing Alex to assist. With practice and tools like Alex, your dev workflow will only get faster and smoother.

Try Alex Alex today and take your iOS projects to the next level!