Mem-build dengan Firebase Data Connect (iOS / Swift)

1. Ringkasan

Codelab ini memandu Anda melalui proses integrasi Firebase Data Connect dengan database Cloud SQL untuk mem-build aplikasi ulasan film untuk iOS menggunakan SwiftUI

Anda akan mempelajari cara menghubungkan aplikasi iOS ke database Cloud SQL menggunakan Firebase Data Connect, yang memungkinkan sinkronisasi data yang lancar untuk ulasan film.

Di akhir codelab ini, Anda akan memiliki aplikasi iOS yang berfungsi dan memungkinkan pengguna menjelajahi film, serta menandai film sebagai favorit, semuanya didukung oleh database Cloud SQL menggunakan kecanggihan Firebase Data Connect.

Yang akan Anda pelajari

Codelab ini akan mengajarkan cara:

  • Siapkan Firebase Data Connect, menggunakan suite Firebase Emulator untuk waktu penyelesaian yang cepat.
  • Buat desain skema database menggunakan Data Connect dan GraphQL.
  • Buat Swift SDK typesafe dari skema database Anda dan tambahkan ke aplikasi Swift.
  • Terapkan autentikasi pengguna dan integrasikan dengan Firebase Data Connect untuk mengamankan data pengguna Anda.
  • Ambil, perbarui, hapus, dan kelola data di Cloud SQL menggunakan kueri dan mutasi yang didukung oleh GraphQL.
  • (Opsional) Deploy layanan Data Connect ke produksi.

Prasyarat

  • Xcode versi terbaru
  • Kode contoh codelab. Anda akan mendownload kode contoh di salah satu langkah pertama codelab.

2. Menyiapkan project contoh

Membuat project Firebase

  1. Login ke Firebase console dengan akun Google Anda.
  2. Di Firebase console, klik Create a Firebase project.
  3. Masukkan nama untuk project Firebase Anda (misalnya, "Friendly Flix"), lalu klik Continue.
  4. Anda mungkin diminta untuk mengaktifkan bantuan AI untuk project Firebase Anda. Untuk tujuan codelab ini, pilihan Anda tidak masalah.
  5. Anda mungkin diminta untuk mengaktifkan Google Analytics. Untuk tujuan codelab ini, pilihan Anda tidak masalah.
  6. Setelah sekitar satu menit, project Firebase Anda akan siap. Klik Lanjutkan.

Mendownload kode

Jalankan perintah berikut untuk meng-clone kode contoh untuk codelab ini. Tindakan ini akan membuat direktori bernama codelab-dataconnect-ios di komputer Anda:

git clone https://github.com/FirebaseExtended/codelab-dataconnect-ios`

Jika tidak memiliki git di komputer, Anda juga dapat mendownload kode langsung dari GitHub.

Menambahkan konfigurasi Firebase

Firebase SDK menggunakan file konfigurasi untuk terhubung ke project Firebase Anda. Di platform Apple, file ini disebut GoogleServices-Info.plist. Pada langkah ini, Anda akan mendownload file konfigurasi dan menambahkannya ke project Xcode.

  1. Di Firebase console, pilih Project Overview di panel navigasi sebelah kiri.
  2. Klik tombol iOS+ untuk memilih platform. Saat diminta memasukkan ID paket Apple, gunakan com.google.firebase.samples.FriendlyFlix
  3. Klik Register app dan ikuti petunjuk untuk mendownload file GoogleServices-Info.plist.
  4. Pindahkan file yang didownload ke direktori start/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/ kode yang baru saja Anda download, yang akan mengganti file GoogleServices-Info.plist yang ada.
  5. Kemudian, klik Berikutnya beberapa kali untuk menyelesaikan project penyiapan di Firebase console (Anda tidak perlu menambahkan SDK ke aplikasi, karena hal ini telah dilakukan untuk Anda di project awal).
  6. Terakhir, klik Lanjutkan ke konsol untuk menyelesaikan proses penyiapan.

3. Menyiapkan Data Connect

Penginstalan

Penginstalan otomatis

Jalankan perintah berikut di direktori codelab-dataconnect-ios/FriendlyFlix:

curl -sL https://firebase.tools/dataconnect | bash

Skrip ini mencoba menyiapkan lingkungan pengembangan untuk Anda dan meluncurkan IDE berbasis browser. IDE ini menyediakan alat, termasuk ekstensi VS Code yang dipaketkan sebelumnya, untuk membantu Anda mengelola skema dan menentukan kueri serta mutasi yang akan digunakan dalam aplikasi, serta membuat SDK dengan jenis yang kuat.

Setelah menjalankan skrip, VS Code akan otomatis terbuka.

Setelah melakukannya sekali, Anda dapat memulai VS Code dengan menjalankan VS Code di direktori lokal:

code .

Penginstalan manual

  1. Menginstal Visual Studio Code
  2. Menginstal Node.js
  3. Di VS Code, buka direktori codelab-dataconnect-ios/FriendlyFlix.
  4. Instal ekstensi Firebase Data Connect dari Visual Studio Code Marketplace.

Melakukan inisialisasi Data Connect dalam project

Di panel sebelah kiri, klik ikon Firebase untuk membuka UI ekstensi Data Connect VS Code

  1. Klik tombol Sign in with Google. Jendela browser akan terbuka; ikuti petunjuk untuk login ke ekstensi dengan Akun Google Anda.
  2. Klik tombol Connect a Firebase project dan pilih project yang Anda buat sebelumnya di konsol.
  3. Klik tombol Run firebase init dan ikuti langkah-langkah di terminal terintegrasi.

Mengonfigurasi pembuatan SDK

Setelah Anda mengklik tombol Run firebase init, ekstensi Firebase Data Connect akan melakukan inisialisasi direktori dataconnect untuk Anda.

Di VS Code, buka file dataconnect/connector/connector.yaml dan Anda akan menemukan konfigurasi default.

Perbarui konfigurasi dan gunakan setelan berikut untuk memastikan kode yang dihasilkan berfungsi dengan codelab ini. Secara khusus, pastikan connectorId ditetapkan ke friendly-flix, dan paket Swift ke FriendlyFlixSDK.

connectorId: "friendly-flix"
generate:
  swiftSdk:
    outputDir: "../../app"
    package: "FriendlyFlixSDK"
    observablePublisher: observableMacro

Berikut adalah arti setelan ini:

  • connectorId - nama unik untuk konektor ini.
  • outputDir - jalur tempat Data Connect SDK yang dihasilkan akan disimpan. Jalur ini relatif terhadap direktori yang berisi file connector.yaml.
  • package - nama paket yang akan digunakan untuk paket Swift yang dihasilkan.

Setelah Anda menyimpan file ini, Firebase Data Connect akan membuat paket Swift bernama FriendlyFlixSDK untuk Anda, dan menempatkannya di samping folder project FriendlyFlix.

Memulai emulator Firebase

Di VS Code, beralihlah ke tampilan Firebase, lalu klik tombol Start emulators.

Tindakan ini akan memulai Firebase Emulator di terminal terintegrasi. Output-nya akan terlihat seperti ini:

npx -y firebase-tools@latest emulators:start --project <your-project-id>

Menambahkan paket yang dihasilkan ke aplikasi Swift Anda

  1. Buka FriendlyFlix/app/FriendlyFlix/FriendlyFlix.xcodeproj di Xcode
  2. Pilih File > Add Package Dependencies...
  3. Klik Add Local..., lalu tambahkan paket FriendlyFlixSDK dari folder FriendlyFlix/app
  4. Tunggu hingga Xcode menyelesaikan dependensi paket.
  5. Pada dialog Choose Package Products for FriendlyFlixSDK, pilih FriendlyFlix sebagai target, lalu klik Add Package.

Mengonfigurasi aplikasi iOS untuk menggunakan emulator lokal

  1. Buka FriendlyFlixApp.swift. (Anda dapat menekan CMD + Shift + O untuk membuka dialog Quick Open, lalu mengetik "FriendlyFlixApp" untuk menemukan file dengan cepat)
  2. Mengimpor Firebase, Firebase Auth, Firebase Data Connect, dan SDK yang dihasilkan untuk skema Anda
  3. Di penginisialisasi, konfigurasikan Firebase.
  4. Pastikan DataConnect dan Firebase Auth menggunakan emulator lokal.
import SwiftUI
import os
import Firebase
import FirebaseAuth
import FriendlyFlixSDK
import FirebaseDataConnect

@main
struct FriendlyFlixApp: App {
  ...

  init() {
    FirebaseApp.configure()
    if useEmulator {
      DataConnect.friendlyFlixConnector.useEmulator(port: 9399)
      Auth.auth().useEmulator(withHost: "localhost", port: 9099)
    }

    authenticationService = AuthenticationService()
  }

  ...

}
  1. Pilih Simulator iOS di dropdown Destination.
  2. Tekan CMD+R (atau klik tombol Run) di Xcode untuk menjalankan aplikasi di Simulator.

4. Menentukan skema dan mengisi otomatis database

Di bagian ini, Anda akan menentukan struktur dan hubungan antara entitas utama dalam aplikasi film dalam skema. Entity seperti Movie, MovieMetaData, dan lainnya dipetakan ke tabel database, dengan hubungan yang dibuat menggunakan Firebase Data Connect dan perintah skema GraphQL.

Entitas dan Hubungan Inti

Model data untuk aplikasi pelacak film ini terdiri dari beberapa entitas yang akan Anda buat selama codelab ini. Anda akan membuat entity inti terlebih dahulu, dan - saat menerapkan lebih banyak fitur - Anda akan menambahkan entity yang diperlukan untuk fitur tersebut.

Pada langkah ini, Anda akan membuat jenis Movie dan MovieMetadata.

Film

Jenis Movie menentukan struktur utama untuk entity film, termasuk kolom seperti title, genre, releaseYear, dan rating.

Di VS Code, tambahkan definisi jenis Movie ke dataconnect/schema/schema.gql:

type Movie @table {
  id: UUID! @default(expr: "uuidV4()")
  title: String!
  imageUrl: String!
  releaseYear: Int
  genre: String
  rating: Float
  description: String
  tags: [String]
}

MovieMetadata

Jenis MovieMetadata menetapkan hubungan satu-ke-satu dengan jenis Movie. Data ini mencakup data tambahan seperti sutradara film.

Tambahkan definisi tabel MovieMetadata ke file dataconnect/schema/schema.gql:

type MovieMetadata @table {
  movie: Movie! @ref
  director: String
}

Kolom dan Default yang Dibuat Otomatis

Skema menggunakan ekspresi seperti @default(expr: "uuidV4()") untuk membuat ID dan stempel waktu unik secara otomatis. Misalnya, kolom id dalam jenis Movie akan otomatis diisi dengan UUID saat data baru dibuat.

Memasukkan data tiruan untuk film dan metadata film

Dengan skema yang ditentukan, Anda kini dapat mengisi otomatis database dengan data tiruan untuk pengujian.

  1. Di Finder, salin finish/FriendlyFlix/dataconnect/moviedata_insert.gql ke folder start/FriendlyFlix/dataconnect.
  2. Di VS Code, buka dataconnect/moviedata_insert.gql.
  3. Pastikan emulator di ekstensi Firebase Data Connect sedang berjalan.
  4. Anda akan melihat tombol Run (local) di bagian atas file. Klik ini untuk menyisipkan data film tiruan ke dalam database Anda.
  5. Periksa terminal Data Connect Execution untuk mengonfirmasi bahwa data berhasil ditambahkan.

Setelah data tersedia, lanjutkan ke langkah berikutnya untuk mempelajari cara membuat kueri di Data Connect.

5. Mengambil dan menampilkan film

Di bagian ini, Anda akan menerapkan fitur untuk menampilkan daftar film.

Pertama, Anda akan mempelajari cara membuat kueri yang mengambil semua film dari tabel movies. Firebase Data Connect menghasilkan kode untuk SDK typesafe yang kemudian dapat Anda gunakan untuk mengeksekusi kueri dan menampilkan film yang diambil di UI aplikasi Anda.

Menentukan kueri ListMovies

Kueri di Firebase Data Connect ditulis dalam GraphQL, sehingga Anda dapat menentukan kolom yang akan diambil. Di FriendlyFlix, layar yang menampilkan film memerlukan kolom berikut: title, description, releaseYear, rating, dan imageUrl. Selain itu, karena ini adalah aplikasi SwiftUI, Anda memerlukan id untuk membantu identitas tampilan SwiftUI.

Di VS Code, buka file dataconnect/connector/queries.gql dan tambahkan kueri ListMovies:

query ListMovies @auth(level: PUBLIC) {
  movies {
    id
    title
    imageUrl
    releaseYear
    genre
    rating
    tags
    description
  }
}

Untuk menguji kueri baru, klik tombol Run (local) untuk menjalankan kueri terhadap database lokal Anda. Daftar film dari database akan ditampilkan di bagian Hasil di terminal Eksekusi Data Connect.

Menghubungkan kueri ListMovies ke layar utama aplikasi

Setelah menguji kueri di Emulator Data Connect, Anda dapat memanggil kueri dari dalam aplikasi.

Saat Anda menyimpan queries.gql, Firebase Data Connect akan membuat kode yang sesuai dengan kueri ListMovies dalam paket FriendlyFlixSDK.

Di Xcode, buka Movie+DataConnect.swift, lalu tambahkan kode berikut untuk memetakan dari ListMoviesQuery.Data.Movie ke Movie:

import FirebaseDataConnect
import FriendlyFlixSDK

extension Movie {
  init(from: ListMoviesQuery.Data.Movie) {
    id = from.id
    title = from.title
    description = from.description ?? ""
    releaseYear = from.releaseYear
    rating = from.rating
    imageUrl = from.imageUrl
  }
}

Buka file HomeScreen.swift dan perbarui menggunakan cuplikan kode berikut.

import SwiftUI
import FirebaseDataConnect
import FriendlyFlixSDK

struct HomeScreen: View {
  ...

  private var connector = DataConnect.friendlyFlixConnector
  let heroMoviesRef: QueryRefObservation<ListMoviesQuery.Data, ListMoviesQuery.Variables>

  init() {
    heroMoviesRef = connector.listMoviesQuery.ref()
  }
}

extension HomeScreen {
  ...

  private var heroMovies: [Movie] {
    heroMoviesRef.data?.movies.map(Movie.init) ?? []
  }

 private var topMovies: [Movie] {
    heroMoviesRef.data?.movies.map(Movie.init) ?? []
  }

  private var watchList: [Movie] {
    heroMoviesRef.data?.movies.map(Movie.init) ?? []
  }

  ...
}

Kueri listMoviesQuery() dibuat oleh Data Connect saat Anda menyimpan queries.gql. Untuk melihat penerapan Swift-nya, lihat file FriendlyFlixOperations.swift dalam paket FriendlyFlixSDK.

Menjalankan aplikasi

Di Xcode, klik tombol Run untuk meluncurkan aplikasi di Simulator iOS.

Setelah aplikasi diluncurkan, Anda akan melihat layar yang terlihat seperti ini:

Anda mungkin melihat bahwa semua area aplikasi (bagian hero, film teratas, dan daftar tontonan) menampilkan daftar yang sama. Hal ini karena Anda menggunakan kueri yang sama untuk semua tampilan tersebut. Di bagian berikutnya, Anda akan menerapkan kueri kustom.

6. Menampilkan film utama dan film teratas

Pada langkah ini, Anda akan berfokus untuk memperbarui cara film ditampilkan di bagian hero – yaitu carousel yang terlihat jelas di bagian atas layar utama – dan juga di bagian film teratas di bawah.

Saat ini, kueri ListMovies mengambil semua film. Untuk mengoptimalkan tampilan bagian ini, Anda akan membatasi jumlah film yang ditampilkan oleh setiap kueri. Implementasi kueri ListMovies saat ini belum menawarkan dukungan bawaan untuk membatasi hasil. Anda akan menambahkan dukungan untuk pembatasan dan pengurutan di bagian ini.

Meningkatkan kueri ListMovies

Buka queries.gql dan perbarui ListMovies sebagai berikut untuk menambahkan dukungan untuk pengurutan dan pembatasan:

query ListMovies(
  $orderByRating: OrderDirection
  $orderByReleaseYear: OrderDirection
  $limit: Int
) @auth(level: PUBLIC) {
  movies(
    orderBy: [{ rating: $orderByRating }, { releaseYear: $orderByReleaseYear }]
    limit: $limit
  ) {
    id
    title
    description
    releaseYear
    rating
    imageUrl
  }
}

Tindakan ini akan memungkinkan Anda membatasi jumlah film yang ditampilkan kueri, dan mengurutkan kumpulan hasil berdasarkan rating dan tahun rilis.

Setelah Anda menyimpan file ini, Firebase Data Connect akan otomatis membuat ulang kode dalam FriendlyFlixSDK. Pada langkah berikutnya, Anda dapat mengupdate kode di HomeScreen.swift untuk memanfaatkan fitur tambahan ini.

Menggunakan kueri yang ditingkatkan di UI

Kembali ke Xcode untuk membuat perubahan yang diperlukan pada HomeScreen.swift.

Pertama, update heroMoviesRef untuk mengambil 3 film yang baru dirilis:

struct HomeScreen {
  ...

  init() {
    heroMoviesRef = connector.listMoviesQuery
      .ref { optionalVars in
        optionalVars.limit = 3
        optionalVars.orderByReleaseYear = .DESC
      }

  }
}

Selanjutnya, siapkan referensi kueri lain untuk film teratas, dan tetapkan filter ke 5 film dengan rating tertinggi:

struct HomeScreen {
  ...

  let topMoviesRef: QueryRefObservation<ListMoviesQuery.Data, ListMoviesQuery.Variables>

  init() {
    heroMoviesRef = ...

    topMoviesRef = connector.listMoviesQuery
      .ref { optionalVars in
        optionalVars.limit = 5
        optionalVars.orderByRating = .DESC
      }
  }
}

Terakhir, perbarui properti komputasi yang menghubungkan hasil kueri ini ke UI:

extension HomeScreen {
  ...

  private var topMovies: [Movie] {
    topMoviesRef.data?.movies.map(Movie.init) ?? []
  }

}

Lihat cara kerjanya

Jalankan kembali aplikasi untuk melihat 3 film terbaru di bagian hero, dan 5 film dengan rating tertinggi di bagian film teratas:

7. Menampilkan detail film dan aktor

Pengguna kini dapat menjelajahi film. Saat mengetuk kartu film, mereka akan melihat beberapa detail tentang film tersebut, tetapi Anda mungkin telah melihat bahwa detailnya kurang detail.

Hal ini karena kita hanya mengambil detail sebanyak mungkin tentang setiap film yang diperlukan untuk merender bagian hero film dan bagian film teratas: judul film, deskripsi singkat, dan URL gambar.

Di halaman detail film, kita ingin menampilkan informasi selengkapnya tentang film tersebut. Di bagian ini, Anda akan meningkatkan aplikasi agar dapat menampilkan aktor film dan ulasan apa pun di halaman detail.

Untuk melakukannya, Anda harus melakukan beberapa hal:

  • Meningkatkan skema untuk mendukung aktor dan ulasan film
  • Menulis kueri Firebase Data Connect untuk mengambil detail tentang film tertentu
  • Menampilkan hasil di layar detail film

Meningkatkan skema

Di VS Code, buka dataconnect/schema/schema.gql dan tambahkan definisi skema untuk Actor dan MovieActor.

## Actors
## An actor can participate in multiple movies; movies can have multiple actors
## Movie - Actors (or vice versa) is a many to many relationship
type Actor @table {
  id: UUID!
  imageUrl: String!
  name: String! @col(name: "name", dataType: "varchar(30)")
}

## Join table for many-to-many relationship for movies and actors
## The 'key' param signifies the primary key(s) of this table
## In this case, the keys are [movieId, actorId], the generated fields of the reference types [movie, actor]
type MovieActor @table(key: ["movie", "actor"]) {
  ## @ref creates a field in the current table (MovieActor) that holds the primary key of the referenced type
  ## In this case, @ref(fields: "id") is implied
  movie: Movie!
  ## movieId: UUID! <- this is created by the implied @ref, see: implicit.gql

  actor: Actor!
  ## actorId: UUID! <- this is created by the implied  @ref, see: implicit.gql

  role: String! ## "main" or "supporting"
}

Menambahkan data tiruan untuk aktor

Dengan skema yang diperbarui, Anda kini dapat mengisi database dengan lebih banyak data tiruan untuk pengujian.

  1. Di Finder, salin finish/FriendlyFlix/dataconnect/moviededetails_insert.gql ke folder start/FriendlyFlix/dataconnect.
  2. Di VS Code, buka dataconnect/moviededetails_insert.gql.
  3. Pastikan emulator di ekstensi Firebase Data Connect sedang berjalan.
  4. Anda akan melihat tombol Run (local) di bagian atas file. Klik ini untuk menyisipkan data film tiruan ke dalam database Anda.
  5. Periksa terminal Eksekusi Data Connect untuk mengonfirmasi bahwa data berhasil ditambahkan.

Setelah data tersedia, lanjutkan ke langkah berikutnya untuk menentukan kueri guna mengambil detail film.

Menentukan kueri GetMovieById

Di VS Code, buka file dataconnect/connector/queries.gql dan tambahkan kueri GetMovieById:

## Get movie by id
query GetMovieById($id: UUID!) @auth(level: PUBLIC) {
  movie(id: $id) {
    id
    title
    imageUrl
    releaseYear
    genre
    rating
    description
    tags
    metadata: movieMetadatas_on_movie {
      director
    }
    mainActors: actors_via_MovieActor(where: { role: { eq: "main" } }) {
      id
      name
      imageUrl
    }
    supportingActors: actors_via_MovieActor(
      where: { role: { eq: "supporting" } }
    ) {
      id
      name
      imageUrl
    }
  }
}

Menghubungkan kueri GetMovieById ke MovieDetailsView

Di Xcode, buka file MovieDetailsView.swift dan perbarui properti komputasi movieDetails agar cocok dengan kode berikut:

import NukeUI
import SwiftUI
import FirebaseDataConnect
import FriendlyFlixSDK

@MainActor
struct MovieDetailsView: View {
  private var movie: Movie

  private var movieDetails: MovieDetails? {
    DataConnect.friendlyFlixConnector
      .getMovieByIdQuery
      .ref(id: movie.id)
      .data?.movie.map { movieDetails in
        MovieDetails(
          title: movieDetails.title,
          description: movieDetails.description ?? "",
          releaseYear: movieDetails.releaseYear,
          rating: movieDetails.rating ?? 0,
          imageUrl: movieDetails.imageUrl,
          mainActors: movieDetails.mainActors.map { mainActor in
            MovieActor(id: mainActor.id,
                       name: mainActor.name,
                       imageUrl: mainActor.imageUrl)
          },
          supportingActors: movieDetails.supportingActors.map{ supportingActor in
            MovieActor(id: supportingActor.id,
                       name: supportingActor.name,
                       imageUrl: supportingActor.imageUrl)
          },
          reviews: []
        )
      }
  }

  public init(movie: Movie) {
    self.movie = movie
  }
}

Menjalankan aplikasi

Di Xcode, klik tombol Run untuk meluncurkan aplikasi di Simulator iOS.

Setelah aplikasi diluncurkan, ketuk kartu film untuk menampilkan detail film. Kodenya akan terlihat seperti berikut:

8. Mengimplementasikan autentikasi pengguna

Saat ini, aplikasi menampilkan informasi film dan aktor yang tidak dipersonalisasi. Pada langkah-langkah berikut, Anda akan menerapkan fitur yang mengaitkan data dengan pengguna yang login. Anda akan memulai dengan mengizinkan pengguna menambahkan film ke daftar tontonan pribadi mereka.

Sebelum dapat menerapkan fitur daftar yang dipantau, Anda harus menetapkan identitas pengguna terlebih dahulu. Untuk mengaktifkannya, Anda akan mengintegrasikan Firebase Authentication, yang memungkinkan pengguna login ke aplikasi.

Anda mungkin telah melihat tombol avatar pengguna di kanan atas layar utama. Mengetuk tombol ini akan mengarahkan Anda ke layar tempat pengguna dapat mendaftar atau login menggunakan email dan sandi mereka.

Setelah pengguna berhasil login, aplikasi Anda harus menyimpan detail penting mereka, terutama ID pengguna unik dan nama pengguna yang dipilih.

Mengaktifkan Firebase Authentication

Di Firebase console untuk project Anda, buka bagian Authentication, lalu aktifkan Firebase Authentication. Kemudian, aktifkan penyedia autentikasi Email/Sandi.

Di folder project lokal, temukan firebase.json dan perbarui seperti berikut untuk mengaktifkan emulator Firebase Authentication.

{
  "emulators": {
    "dataconnect": {
    },
    "auth": {
    }
  },
  "dataconnect": {
    "source": "dataconnect"
  }
}

Setelah itu, Anda harus menghentikan dan memulai ulang Firebase Emulator agar perubahan diterapkan.

Menerapkan pengendali autentikasi

Di bagian berikut, Anda akan menerapkan logika yang menghubungkan autentikasi pengguna dengan database. Hal ini melibatkan pembuatan pengendali autentikasi yang memproses login yang berhasil.

Setelah pengguna diautentikasi, pengendali ini akan otomatis memicu pembuatan akun yang sesuai di database Anda.

Di Xcode, buka file AuthenticationService.swift dan tambahkan kode berikut:

import Foundation
import Observation
import os
import FirebaseAuth

enum AuthenticationState {
  case unauthenticated
  case authenticating
  case authenticated
}

@Observable
class AuthenticationService {
  private let logger = Logger(subsystem: "FriendlyFlix", category: "auth")

  var presentingAuthenticationDialog = false
  var presentingAccountDialog = false

  var authenticationState: AuthenticationState = .unauthenticated
  var user: User?
  private var authenticationListener: AuthStateDidChangeListenerHandle?

  init() {
    authenticationListener = Auth.auth().addStateDidChangeListener { auth, user in
      if let user {
        self.authenticationState = .authenticated
        self.user = user
      } else {
        self.authenticationState = .unauthenticated
      }
    }
  }

  private var onSignUp: ((User) -> Void)?
  public func onSignUp(_ action: @escaping (User) -> Void) {
    onSignUp = action
  }

  func signInWithEmailPassword(email: String, password: String) async throws {
    try await Auth.auth().signIn(withEmail: email, password: password)
    authenticationState = .authenticated
  }

  func signUpWithEmailPassword(email: String, password: String) async throws {
    try await Auth.auth().createUser(withEmail: email, password: password)

    if let onSignUp, let user = Auth.auth().currentUser {
      logger
        .debug(
          "User signed in \(user.displayName ?? "(no fullname)") with email \(user.email ?? "(no email)")"
        )
      onSignUp(user)
    }

    authenticationState = .authenticated
  }

  func signOut() throws {
    try Auth.auth().signOut()
    authenticationState = .unauthenticated
  }
}

Ini adalah pengendali autentikasi generik yang memungkinkan Anda menggunakan onSignUp untuk mendaftarkan penutupan yang akan dipanggil saat pengguna login.

Di dalam penutupan tersebut, Anda dapat membuat akun pengguna baru di database. Namun, sebelum dapat melakukannya, Anda perlu membuat mutasi yang memungkinkan Anda membuat atau memperbarui pengguna baru di database.

Menambahkan entitas Pengguna ke skema

Jenis User menentukan entity pengguna. Pengguna dapat berinteraksi dengan film dengan memberikan ulasan atau memfavoritkan film.

Di VS Code, buka file dataconnect/schema/schema.gql dan tambahkan definisi tabel User berikut:

## Users
## A user can leave reviews for movies
## user-reviews is a one to many relationship, movie-reviews is a one to many relationship, movie:user is a many to many relationship
type User @table {
  id: String! @col(name: "user_auth")
  username: String! @col(name: "username", dataType: "varchar(50)")
}

Menentukan mutasi untuk menyisipkan atau memperbarui pengguna

Di VS Code, buka file dataconnect/connector/mutations.gql dan tambahkan mutasi UpsertUser:

mutation UpsertUser($username: String!) @auth(level: USER) {
  user_upsert(
    data: {
      id_expr: "auth.uid"
      username: $username
    }
  )
}

Membuat pengguna baru setelah berhasil login

Di Xcode, buka FriendlyFlixApp.swift, lalu tambahkan kode berikut ke penginisialisasi:

@main
struct FriendlyFlixApp: App {

  ...

  init() {
    ...
    authenticationService = AuthenticationService()
    authenticationService?.onSignUp { user in
      let userName = String(user.email?.split(separator: "@").first ?? "(unknown)")
      Task {
        try await DataConnect.friendlyFlixConnector
          .upsertUserMutation.execute(username: userName)
      }
    }
  }

  var body: some Scene {
    ...
  }
}

Kode ini menggunakan upsertUserMutation Firebase Data Connect yang dibuat untuk Anda guna menyisipkan pengguna baru (atau memperbarui pengguna yang ada dengan ID yang sama) setiap kali pengguna berhasil mendaftar menggunakan Firebase Authentication.

Lihat cara kerjanya

Untuk memverifikasi bahwa hal ini berfungsi, daftar terlebih dahulu di aplikasi iOS:

  • Jika belum, hentikan dan mulai ulang Firebase Emulator untuk memastikan Firebase Authentication Emulator sedang berjalan.
  • Di Xcode, klik tombol Run untuk meluncurkan aplikasi di Simulator iOS.
  • Klik ikon avatar di sudut kanan atas layar.
  • Beralih ke alur Daftar dan daftar ke aplikasi.

Kemudian, buat kueri database untuk memverifikasi bahwa aplikasi telah membuat akun pengguna baru untuk pengguna:

  • Di VS Code, buka dataconnect/schema/schema.gql dan klik Read data pada entitas User
  • Tindakan ini akan membuat file kueri baru, bernama User_read.gql
  • Klik Jalankan lokal untuk melihat semua pengguna di tabel pengguna
  • Di panel Eksekusi Koneksi Data, Anda akan melihat akun untuk pengguna yang baru saja Anda daftarkan dengan

9. Mengelola film favorit

Di bagian codelab ini, Anda akan menerapkan interaksi pengguna di aplikasi ulasan film, khususnya memungkinkan pengguna mengelola film favorit mereka. Film yang ditandai sebagai favorit akan muncul di bagian daftar tontonan aplikasi.

Meningkatkan skema untuk mendukung favorit

Jenis FavoriteMovie adalah tabel join yang menangani hubungan many-to-many antara pengguna dan film favorit mereka. Setiap tabel menautkan User ke Movie.

Salin dan tempel cuplikan kode ke file dataconnect/schema/schema.gql Anda:

type FavoriteMovie
  @table(name: "FavoriteMovies", singular: "favorite_movie", plural: "favorite_movies", key: ["user", "movie"]) {
  ## @ref is implicit
  user: User!
  movie: Movie!
}

Menentukan mutasi untuk menambahkan dan menghapus favorit

Sebelum aplikasi dapat menampilkan film favorit pengguna, pengguna harus menunjukkan film mana yang merupakan favoritnya. Untuk melakukannya, Anda harus menambahkan dua mutasi terlebih dahulu untuk menandai film sebagai salah satu favorit pengguna, atau menghapusnya dari favorit mereka lagi.

  1. Di VS Code, buka mutations.gql di dataconnect/connector/mutations.gql
  2. Tambahkan mutasi berikut untuk menangani film favorit:
## Add a movie to the user's favorites list
mutation AddFavoritedMovie($movieId: UUID!) @auth(level: USER) {
  favorite_movie_upsert(data: { userId_expr: "auth.uid", movieId: $movieId })
}

## Remove a movie from the user's favorites list
mutation DeleteFavoritedMovie($movieId: UUID!) @auth(level: USER) {
  favorite_movie_delete(key: { userId_expr: "auth.uid", movieId: $movieId })
}

Menghubungkan mutasi ke UI aplikasi Anda

Pengguna dapat menandai film sebagai favorit dengan mengklik ikon hati di layar detail film.

Untuk menghubungkan mutasi yang baru saja Anda buat ke UI aplikasi, buat perubahan berikut di MovieCardView:

  1. Mengimpor FriendlyFlixSDK dan menyiapkan konektor
import NukeUI
import os
import SwiftUI
import FirebaseDataConnect
import FriendlyFlixSDK

struct MovieCardView: View {
  private let logger = Logger(subsystem: "FriendlyFlix", category: "moviecard")
  @Environment(\.dismiss) private var dismiss
  private var connector = DataConnect.friendlyFlixConnector

  ...
}
  1. Implementasikan metode toggleFavourite. Metode ini akan dipanggil setiap kali pengguna mengetuk ikon hati di MovieCardView:
struct MovieCardView {

  ...

  private func toggleFavourite() {
    Task {
      if isFavourite {
        let _ = try await connector.deleteFavoritedMovieMutation.execute(movieId: movie.id)
      } else {
        let _ = try await connector.addFavoritedMovieMutation.execute(movieId: movie.id)
      }
    }
  }
}

Tindakan ini akan memperbarui status favorit film saat ini di database. Satu langkah terakhir yang tidak ada adalah memastikan status UI ditampilkan sebagaimana mestinya.

Menentukan kueri untuk mengetahui apakah film ditandai sebagai favorit

  1. Di VS Code, buka queries.gql di dataconnect/connector.
  2. Tambahkan kueri berikut untuk memeriksa apakah film ditandai sebagai favorit:
query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) {
  favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) {
    movieId
  }
}
  1. Di Xcode, Buat instance referensi ke kueri GetIfFavoritedMovie dan terapkan properti yang dihitung yang menentukan apakah film yang ditampilkan di MovieCardView ini ditandai sebagai favorit untuk pengguna saat ini.
struct MovieCardView: View {

  ...

  public init(showDetails: Bool, movie: Movie) {
    self.showDetails = showDetails
    self.movie = movie

    isFavouriteRef = connector.getIfFavoritedMovieQuery.ref(movieId: movie.id)
  }

  // MARK: - Favourite handling

  private let isFavouriteRef: QueryRefObservation<
    GetIfFavoritedMovieQuery.Data,
    GetIfFavoritedMovieQuery.Variables
  >
  private var isFavourite: Bool {
    isFavouriteRef.data?.favorite_movie?.movieId != nil
  }

  ...

}
  1. Perbarui kode di toggleFavourite untuk menjalankan kueri setiap kali pengguna mengetuk tombol. Hal ini memastikan bahwa properti yang dihitung isFavourite selalu menampilkan nilai yang benar.
  private func toggleFavourite() {
    Task {
      if isFavourite {
        ...
      }

      let _ = try await isFavouriteRef.execute()
    }
  }

Mengambil film favorit

Sebagai langkah terakhir untuk fitur ini, Anda akan menerapkan pengambilan film favorit pengguna agar mereka dapat melihatnya di daftar tontonan.

  1. Di VS Code, buka queries.gql di dataconnect/connector/queries.gql dan tempel kueri berikut:
## Get favorite movies by user ID
query GetUserFavoriteMovies @auth(level: USER) {
  user(id_expr: "auth.uid") {
    favoriteMovies: favorite_movies_on_user {
      movie {
        id
        title
        genre
        imageUrl
        releaseYear
        rating
        description
      }
    }
  }
}

Daftar film favorit pengguna ditampilkan di LibraryScreen. Layar ini hanya boleh menampilkan data jika pengguna login, sehingga Anda akan menghubungkan status autentikasi layar ke AuthenticationService aplikasi terlebih dahulu.

  1. Tambahkan kode untuk memetakan dari FavoriteMovieFavoriteMovies ke Movie ke Movie+DataConnect.swift:
import FirebaseDataConnect
import FriendlyFlixSDK

extension Movie {

  ...

  init(from: GetUserFavoriteMoviesQuery.Data.User.FavoriteMovieFavoriteMovies) {
    id = from.movie.id
    title = from.movie.title
    description = from.movie.description ?? ""
    releaseYear = from.movie.releaseYear
    rating = from.movie.rating
    imageUrl = from.movie.imageUrl
  }
}
  1. Di Xcode, buka LibraryScreen, lalu perbarui isSignedIn sebagai berikut:
struct LibraryScreen: View {
  ...

  private var isSignedIn: Bool {
    authenticationService.user != nil
  }

}
  1. Kemudian, impor Firebase Data Connect dan FriendlyFlixSDK, dan dapatkan referensi ke kueri GetUserFavoriteMovies:
import SwiftUI
import FirebaseDataConnect
import FriendlyFlixSDK

struct LibraryScreen {

 ...

  private var connector = DataConnect.friendlyFlixConnector

  ...

  init() {
    watchListRef = connector.getUserFavoriteMoviesQuery.ref()
  }

  private let watchListRef: QueryRefObservation<
    GetUserFavoriteMoviesQuery.Data,
    GetUserFavoriteMoviesQuery.Variables
  >
  private var watchList: [Movie] {
    watchListRef.data?.user?.favoriteMovies.map(Movie.init) ?? []
  }

  ...

}


  1. Pastikan kueri watchListRef dieksekusi saat tampilan muncul:
extension LibraryScreen: View {
  var body: some View {
    ...
            MovieListSection(namespace: namespace, title: "Watch List", movies: watchList)
              .onAppear {
                Task {
                  try await watchListRef.execute()
                }
  ...

Lihat cara kerjanya

Sekarang Anda dapat menjalankan aplikasi dan mencoba fitur favorit yang baru saja diterapkan. Beberapa hal yang perlu diingat:

  • Pastikan Emulator Firebase sedang berjalan
  • Pastikan Anda telah menambahkan data tiruan untuk film dan detail film
  • Pastikan Anda telah mendaftar sebagai pengguna
  1. Di Xcode, klik tombol Run untuk meluncurkan aplikasi di Simulator iOS.
  2. Setelah aplikasi diluncurkan, ketuk kartu film untuk menampilkan detail film.
  3. Ketuk ikon hati untuk menandai film sebagai favorit. Hati akan berubah menjadi solid.
  4. Ulangi langkah ini untuk beberapa film.
  5. Buka tab Koleksi. Sekarang Anda akan melihat daftar semua film yang Anda tandai sebagai favorit.

10. Selamat

Selamat, Anda telah berhasil menambahkan Firebase Data Connect ke aplikasi iOS. Sekarang Anda sudah mengetahui langkah-langkah utama yang diperlukan untuk menyiapkan Data Connect, membuat kueri dan mutasi, serta menangani autentikasi pengguna.

Opsional: men-deploy ke produksi

Sejauh ini, aplikasi ini hanya menggunakan Emulator Firebase. Jika Anda ingin mempelajari cara men-deploy aplikasi ini ke project Firebase sungguhan, lanjutkan ke langkah berikutnya.

11. (Opsional) Men-deploy aplikasi

Sejauh ini aplikasi ini sepenuhnya bersifat lokal, semua datanya terdapat di Firebase Emulator Suite. Di bagian ini, Anda akan mempelajari cara mengonfigurasi project Firebase agar aplikasi ini dapat berfungsi dalam produksi.

Mengaktifkan Firebase Authentication

  1. Di Firebase console, buka bagian Authentication, lalu klik Get started.
  2. Buka tab Metode login .
  3. Pilih opsi Email/Sandi dari bagian penyedia native,
  4. Aktifkan penyedia Email/Sandi, lalu klik Simpan.

Mengaktifkan Firebase Data Connect

Penting: Jika ini adalah pertama kalinya Anda men-deploy skema dalam project, proses ini akan membuat instance PostgreSQL Cloud SQL, yang dapat memerlukan waktu sekitar 15 menit. Anda tidak akan dapat men-deploy hingga instance Cloud SQL siap dan terintegrasi dengan Firebase Data Connect.

1. Di UI ekstensi Firebase Data Connect VS Code, klik Deploy to production. 2. Anda mungkin perlu meninjau perubahan skema dan menyetujui modifikasi yang berpotensi merusak. Anda akan diminta untuk: - Meninjau perubahan skema menggunakan firebase dataconnect:sql:diff - Jika Anda puas dengan perubahan, terapkan perubahan tersebut menggunakan alur yang dimulai oleh firebase dataconnect:sql:migrate

Instance Cloud SQL untuk PostgreSQL Anda akan diperbarui dengan skema dan data akhir yang di-deploy. Anda dapat memantau statusnya di Firebase Console.

Sekarang Anda dapat mengklik Run (Production) di panel Firebase Data Connect, seperti yang Anda lakukan dengan emulator lokal, untuk menambahkan data ke lingkungan produksi.

Sebelum menjalankan aplikasi iOS lagi, pastikan aplikasi terhubung ke instance produksi project Anda:

  1. Buka menu Product > Scheme > Edit Scheme....
  2. Di bagian Run, hapus centang pada argumen peluncuran -useEmulator YES.