1. Omówienie
Ten moduł Codelab przeprowadzi Cię przez proces integracji usługi Firebase Data Connect z bazą danych Cloud SQL w celu tworzenia aplikacji do recenzowania filmów na iOS za pomocą SwiftUI.
Dowiesz się, jak połączyć aplikację na iOS z bazą danych Cloud SQL za pomocą Firebase Data Connect, co umożliwi płynną synchronizację danych w przypadku recenzji filmów.
Po zakończeniu tego ćwiczenia będziesz mieć działającą aplikację na iOS, która umożliwia użytkownikom przeglądanie filmów i oznaczanie ich jako ulubionych. Wszystko to jest obsługiwane przez bazę danych Cloud SQL za pomocą usługi Firebase Data Connect.
Czego się nauczysz
Z tego ćwiczenia dowiesz się, jak:
- Skonfiguruj Firebase Data Connect, korzystając z pakietu emulatorów Firebase, aby skrócić czas realizacji.
- Zaprojektuj schemat bazy danych za pomocą Data Connect i GraphQL.
- Utwórz pakiet SDK Swift z zabezpieczeniami typów na podstawie schematu bazy danych i dodaj go do aplikacji Swift.
- Wdrożyć uwierzytelnianie użytkowników i zintegrować je z Firebase Data Connect, aby chronić dane użytkowników.
- Pobieraj, aktualizuj i usuwaj dane w Cloud SQL oraz zarządzaj nimi za pomocą zapytań i mutacji opartych na GraphQL.
- (Opcjonalnie) Wdróż usługę Data Connect w środowisku produkcyjnym.
Wymagania wstępne
- najnowsza wersja Xcode,
- Przykładowy kod w laboratorium kodu. Przykładowy kod pobierzesz w jednym z pierwszych kroków w codelab.
2. Konfigurowanie przykładowego projektu
Tworzenie projektu Firebase
- Zaloguj się w konsoli Firebase za pomocą konta Google.
- W konsoli Firebase kliknij Utwórz projekt Firebase.
- Wpisz nazwę projektu Firebase (np. „Friendly Flix”), a potem kliknij Dalej.
- Możesz zostać poproszony(-a) o włączenie pomocy AI w projekcie Firebase. Na potrzeby tego ćwiczenia wybór nie ma znaczenia.
- Może pojawić się prośba o włączenie Google Analytics. W ramach tego ćwiczenia wybór nie ma znaczenia.
- Po około minucie Twój projekt Firebase będzie gotowy. Kliknij Dalej.
Pobieranie kodu
Aby skopiować przykładowy kod do tego ćwiczenia, uruchom to polecenie. Spowoduje to utworzenie na komputerze katalogu o nazwie codelab-dataconnect-ios
:
git clone https://github.com/peterfriese/codelab-dataconnect-ios`
Jeśli nie masz git na komputerze, możesz też pobrać kod bezpośrednio z GitHuba.
Dodawanie konfiguracji Firebase
Pakiet SDK Firebase używa pliku konfiguracyjnego do łączenia się z projektem Firebase. Na platformach Apple ten plik nazywa się GoogleServices-Info.plist
. W tym kroku pobierzesz plik konfiguracji i dodasz go do projektu Xcode.
- W konsoli Firebase kliknij Przegląd projektu w menu nawigacyjnym po lewej stronie.
- Kliknij przycisk iOS+, aby wybrać platformę. Gdy pojawi się prośba o identyfikator pakietu Apple, użyj
com.google.firebase.samples.FriendlyFlix
. - Kliknij Zarejestruj aplikację i postępuj zgodnie z instrukcjami, aby pobrać plik
GoogleServices-Info.plist
. - Przenieś pobrany plik do katalogu
start/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/
pobranego właśnie kodu, zastępując istniejący plikGoogleServices-Info.plist
. - Następnie kliknij kilka razy Dalej, aby ukończyć konfigurowanie projektu w konsoli Firebase (nie musisz dodawać pakietu SDK do aplikacji, ponieważ zrobiono to już za Ciebie w projekcie startowym).
- Na koniec kliknij Dalej do konsoli, aby zakończyć proces konfiguracji.
3. Konfigurowanie Data Connect
Instalacja
Automatyczna instalacja
W katalogu codelab-dataconnect-ios/FriendlyFlix
uruchom to polecenie:
curl -sL https://firebase.tools/dataconnect | bash
Ten skrypt próbuje skonfigurować środowisko programistyczne i uruchomić IDE w przeglądarce. To środowisko IDE udostępnia narzędzia, w tym wstępnie skompilowane rozszerzenie VS Code, które ułatwia zarządzanie schematem i definiowanie zapytań oraz mutacji do użycia w aplikacji, a także generowanie pakietów SDK o ścisłym typowaniu.
Po uruchomieniu skryptu VS Code powinien otworzyć się automatycznie.
Gdy to zrobisz, możesz uruchomić VS Code, uruchamiając go w katalogu lokalnym:
code .
Instalacja ręczna
- Instalowanie Visual Studio Code
- Zainstaluj Node.js
- W VS Code otwórz katalog
codelab-dataconnect-ios/FriendlyFlix
. - Zainstaluj rozszerzenie Firebase Data Connect ze sklepu Visual Studio Code Marketplace.
Inicjowanie usługi Data Connect w projekcie
W panelu po lewej stronie kliknij ikonę Firebase, aby otworzyć interfejs rozszerzenia Data Connect w VS Code.
- Kliknij przycisk Zaloguj się przez Google. Otworzy się okno przeglądarki. Postępuj zgodnie z instrukcjami, aby zalogować się w rozszerzeniu za pomocą konta Google.
- Kliknij przycisk Połącz z projektem Firebase i wybierz projekt utworzony wcześniej w konsoli.
- Kliknij przycisk Uruchom firebase init i postępuj zgodnie z instrukcjami wyświetlanymi w zintegrowanym terminalu.
Konfigurowanie generowania pakietu SDK
Po kliknięciu przycisku Uruchom init firebase rozszerzenie Firebase Data Connect powinno zainicjować katalog dataconnect
.
W VS Code otwórz plik dataconnect/connector/connector.yaml
, aby znaleźć domyślną konfigurację.
Aby mieć pewność, że wygenerowany kod będzie działać w tym ćwiczeniu, zaktualizuj konfigurację i użyj tych ustawień. W szczególności sprawdź, czy nagłówek connectorId
ma wartość friendly-flix
, a pakiet Swift – wartość FriendlyFlixSDK
.
connectorId: "friendly-flix"
generate:
swiftSdk:
outputDir: "../../app"
package: "FriendlyFlixSDK"
observablePublisher: observableMacro
Oznaczają one:
connectorId
– niepowtarzalna nazwa tego oprogramowania sprzęgającego.outputDir
– ścieżka, na której będzie przechowywany wygenerowany pakiet SDK Data Connect. Ta ścieżka jest względna względem katalogu zawierającego plikconnector.yaml
.package
– nazwa pakietu, która ma być używana w wygenerowanym pakiecie Swift.
Po zapisaniu tego pliku usługa Firebase Data Connect wygeneruje dla Ciebie pakiet Swift o nazwie FriendlyFlixSDK
i umieści go obok folderu projektu FriendlyFlix
.
Uruchom emulatory Firebase.
W VS Code przełącz się na widok Firebase, a potem kliknij przycisk Uruchom emulatory.
Spowoduje to uruchomienie emulatora Firebase w zintegrowanym terminalu. Dane wyjściowe powinny wyglądać tak:
npx -y firebase-tools@latest emulators:start --project <your-project-id>
Dodawanie wygenerowanego pakietu do aplikacji Swift
- Otwórz
FriendlyFlix/app/FriendlyFlix/FriendlyFlix.xcodeproj
w Xcode - Wybierz Plik > Dodaj zależności pakietu….
- Kliknij Dodaj lokalny…, a następnie dodaj pakiet
FriendlyFlixSDK
z folderuFriendlyFlix/app
. - Poczekaj, aż Xcode rozwiąże zależności pakietu.
- W oknie Wybieranie pakietów produktów dla FriendlyFlixSDK wybierz
FriendlyFlix
jako element docelowy i kliknij Dodaj pakiet.
Konfigurowanie aplikacji na iOS do korzystania z lokalnego emulatora
- Otwórz pokój
FriendlyFlixApp.swift
. (aby otworzyć okno Szybkie otwieranie, naciśnij CMD + Shift + O, a potem wpisz „FriendlyFlixApp”, aby szybko znaleźć plik) - Zaimportuj Firebase, Firebase Auth, Firebase Data Connect i wygenerowany pakiet SDK dla swojego schematu.
- W inicjalizacji skonfiguruj Firebase.
- Upewnij się, że DataConnect i Firebase Auth używają emulatora lokalnego.
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()
}
...
}
- W menu Miejsce docelowe wybierz symulator iOS.
- Aby uruchomić aplikację na symulatorze, naciśnij CMD+R (lub kliknij przycisk Uruchom) w Xcode.
4. Zdefiniuj schemat i wstępnie wypełnij bazę danych
W tej sekcji określisz w schemacie strukturę i relacje między najważniejszymi elementami w aplikacji filmowej. Elementy takie jak Movie
, MovieMetaData
i inne są mapowane na tabele bazy danych, a relacje są ustanawiane za pomocą dyrektyw schematu Firebase Data Connect i GraphQL.
Podstawowe elementy i powiązania
Model danych tej aplikacji do śledzenia filmów składa się z kilku encji, które utworzysz w trakcie tego ćwiczenia. Najpierw utworzysz główne typy jednostek, a potem, gdy będziesz wdrażać kolejne funkcje, dodasz typy jednostek wymagane przez te funkcje.
W tym kroku utworzysz typy Movie
i MovieMetadata
.
Film
Typ Movie
definiuje główną strukturę elementu filmu, w tym pola title
, genre
, releaseYear
i rating
.
W VS Code dodaj definicję typu Movie
do pliku 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
Typ MovieMetadata
ustanawia relację jeden-do-jednego z typem Movie
. Zawiera ono dodatkowe dane, takie jak reżyser filmu.
Dodaj do pliku dataconnect/schema/schema.gql
definicję tabeli MovieMetadata
:
type MovieMetadata @table {
movie: Movie! @ref
director: String
}
Pola i ustawienia domyślne utworzone automatycznie
Schemat używa wyrażeń takich jak @default(expr: "uuidV4()")
do automatycznego generowania unikalnych identyfikatorów i sygnatur czasowych. Na przykład pole id
typu Movie
jest automatycznie wypełniane identyfikatorem UUID podczas tworzenia nowego rekordu.
Wstawianie danych testowych dotyczących filmów i metadanych
Po zdefiniowaniu schematu możesz wstępnie wypełnić bazę danych testowymi danymi.
- W Finderze skopiuj
finish/FriendlyFlix/dataconnect/moviedata_insert.gql
do folderustart/FriendlyFlix/dataconnect
. - W VS Code otwórz
dataconnect/moviedata_insert.gql
. - Upewnij się, że emulatory w rozszerzeniu Firebase Data Connect są uruchomione.
- U góry pliku powinien pojawić się przycisk Uruchom (lokalnie). Kliknij, aby wstawić do bazy danych dane testowe filmu.
- Sprawdź terminal Wykonanie usługi Data Connect, aby potwierdzić, że dane zostały dodane.
Gdy dane są już dostępne, przejdź do następnego kroku, aby dowiedzieć się, jak tworzyć zapytania w Data Connect.
5. Pobieranie i wyświetlanie filmów
W tej sekcji zaimplementujesz funkcję wyświetlania listy filmów.
Najpierw dowiesz się, jak utworzyć zapytanie, które zwraca wszystkie filmy z tabeli movies
. Firebase Data Connect generuje kod pakietu SDK z zabezpieczeniem typów, którego możesz użyć do wykonania zapytania i wyświetlenia pobranych filmów w interfejsie aplikacji.
Definiowanie zapytania ListMovies
Zapytania w Firebase Data Connect są pisane w języku GraphQL, co pozwala określić, które pola mają być pobierane. W FriendlyFlix ekrany, na których wyświetlane są filmy, wymagają tych pól: title
, description
, releaseYear
, rating
i imageUrl
. Ponieważ jest to aplikacja SwiftUI, musisz też użyć id
, aby pomóc w identyfikacji widoku SwiftUI.
W VS Code otwórz plik dataconnect/connector/queries.gql
i dodaj zapytanie ListMovies
:
query ListMovies @auth(level: PUBLIC) {
movies {
id
title
imageUrl
releaseYear
genre
rating
tags
description
}
}
Aby przetestować nowe zapytanie, kliknij przycisk Uruchom (lokalnie), aby wykonać zapytanie w bazie danych lokalnej. Lista filmów z bazy danych powinna być wyświetlana w sekcji Wyniki w terminalu wykonania Data Connect.
Połącz zapytanie ListMovies z ekranem głównym aplikacji
Po przetestowaniu zapytania w edytorze Data Connect możesz je wywołać z aplikacji.
Gdy zapiszesz queries.gql
, Firebase Data Connect wygeneruje kod odpowiadający zapytaniu ListMovies
w pakiecie FriendlyFlixSDK
.
W Xcode otwórz plik Movie+DataConnect.swift
i dodaj ten kod, aby mapować z ListMoviesQuery.Data.Movie
na 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
}
}
Otwórz plik HomeScreen.swift
i zaktualizuj go za pomocą tego fragmentu kodu.
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) ?? []
}
...
}
Zapytanie |
Uruchamianie aplikacji
W Xcode kliknij przycisk Uruchom, aby uruchomić aplikację w symulatorze iOS.
Po uruchomieniu aplikacji powinien pojawić się ekran podobny do tego:
Możesz zauważyć, że wszystkie obszary aplikacji (sekcja główna, najpopularniejsze filmy i lista do obejrzenia) wyświetlają tę samą listę. Dzieje się tak, ponieważ używasz tego samego zapytania we wszystkich tych widokach. W kolejnych sekcjach zaimplementujesz zapytania niestandardowe. |
6. Wyświetlanie filmu głównego i najpopularniejszych filmów
W tym kroku skoncentrujemy się na zmianie sposobu wyświetlania filmów w sekcji głównej (czyli w obszernej karuzeli na górze ekranu głównego) oraz w sekcji Najlepsze filmy poniżej.
Obecnie zapytanie ListMovies zwraca wszystkie filmy. Aby zoptymalizować wyświetlanie w tych sekcjach, ogranicz liczbę filmów zwracanych przez każde zapytanie. Obecna implementacja zapytania ListMovies
nie obsługuje jeszcze wbudowanego ograniczania wyników. W tej sekcji dodasz obsługę ograniczania i sortowania.
Ulepszanie zapytania ListMovies
Aby dodać obsługę sortowania i ograniczania, otwórz queries.gql
i zaktualizuj ListMovies
w ten sposób:
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
}
}
Dzięki temu możesz ograniczyć liczbę filmów zwracanych przez zapytanie i posortować zbiór wyników według oceny i roku wydania.
Po zapisaniu tego pliku usługa Firebase Data Connect automatycznie wygeneruje kod w ramach FriendlyFlixSDK
. W następnym kroku możesz zaktualizować kod w pliku HomeScreen.swift
, aby korzystać z tych dodatkowych funkcji.
Korzystanie z rozszerzonego zapytania w interfejsie
Wróć do Xcode, aby wprowadzić wymagane zmiany w plikach HomeScreen.swift
.
Najpierw zaktualizuj heroMoviesRef
, aby pobrać 3 ostatnio wydane filmy:
struct HomeScreen {
...
init() {
heroMoviesRef = connector.listMoviesQuery
.ref { optionalVars in
optionalVars.limit = 3
optionalVars.orderByReleaseYear = .DESC
}
}
}
Następnie skonfiguruj kolejną referencję zapytania dla najpopularniejszych filmów i ustaw filtr na 5 najwyżej ocenionych filmów:
struct HomeScreen {
...
let topMoviesRef: QueryRefObservation<ListMoviesQuery.Data, ListMoviesQuery.Variables>
init() {
heroMoviesRef = ...
topMoviesRef = connector.listMoviesQuery
.ref { optionalVars in
optionalVars.limit = 5
optionalVars.orderByRating = .DESC
}
}
}
Na koniec zaktualizuj obliczalną właściwość, która łączy wynik tego zapytania z interfejsem:
extension HomeScreen {
...
private var topMovies: [Movie] {
topMoviesRef.data?.movies.map(Movie.init) ?? []
}
}
Zobacz, jak to działa
Uruchom ponownie aplikację, aby zobaczyć 3 najnowsze filmy w sekcji głównej i 5 filmów z najlepszymi ocenami w sekcji Najlepsze filmy:
7. Wyświetlanie szczegółów filmu i aktorów
Użytkownik może teraz przeglądać filmy. Po kliknięciu karty filmu wyświetlają się pewne informacje o filmie, ale być może zauważysz, że brakuje im pewnych szczegółów.
Wynika to z tego, że pobieraliśmy tylko tyle informacji o każdym filmie, ile było nam potrzebne do renderowania sekcji z filmem w centrum uwagi i sekcji Najpopularniejsze filmy: tytuł filmu, krótki opis i adres URL obrazu.
Na stronie z informacjami o filmie chcemy wyświetlać więcej informacji o danym filmie. W tej sekcji ulepszysz aplikację, aby wyświetlała aktorów i opinie o filmie na stronie z informacjami.
Aby to zrobić, musisz wykonać kilka czynności:
- Ulepszenie schematu w celu obsługi aktorów i recenzji filmów
- Tworzenie zapytań Firebase Data Connect służących do pobierania szczegółów danego filmu
- Wyświetlanie wyników na ekranie z informacjami o filmie
Ulepszanie schematu
W VS Code otwórz plik dataconnect/schema/schema.gql
i dodaj definicje schematu dla Actor
i 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"
}
Dodawanie danych testowych dla aktorów
Po zaktualizowaniu schematu możesz wypełnić bazę danych większą ilością danych testowych.
- W Finderze skopiuj
finish/FriendlyFlix/dataconnect/moviededetails_insert.gql
do folderustart/FriendlyFlix/dataconnect
. - W VS Code otwórz
dataconnect/moviededetails_insert.gql
. - Upewnij się, że emulatory w rozszerzeniu Firebase Data Connect działają.
- U góry pliku powinien pojawić się przycisk Uruchom (lokalnie). Kliknij, aby wstawić do bazy danych dane testowe filmu.
- Sprawdź terminal Data Connect Execution, aby potwierdzić, że dane zostały dodane.
Gdy dane są już gotowe, przejdź do następnego kroku, aby zdefiniować zapytanie służące do pobierania szczegółów filmu.
Definiowanie zapytania GetMovieById
W VS Code otwórz plik dataconnect/connector/queries.gql
i dodaj zapytanie 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
}
}
}
Połącz zapytanie GetMovieById z widokiem MovieDetailsView
W Xcode otwórz plik MovieDetailsView.swift
i zaktualizuj obliczalną właściwość movieDetails
, aby odpowiadała temu kodowi:
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
}
}
Uruchamianie aplikacji
W Xcode kliknij przycisk Uruchom, aby uruchomić aplikację w symulatorze iOS.
Po uruchomieniu aplikacji kliknij kartę filmu, aby wyświetlić jego szczegóły. Powinien on wyglądać podobnie do tego:
8. Wdrażanie uwierzytelniania użytkowników
Obecnie aplikacja wyświetla niespersonalizowane informacje o filmach i aktorach. W następnych krokach zaimplementujesz funkcje, które kojarzą dane z zalogowanym użytkownikiem. Zacznij od umożliwienia użytkownikom dodawania filmów do ich osobistej listy Do obejrzenia.
Zanim zaczniesz stosować funkcję listy obserwacyjnej, musisz najpierw ustalić tożsamość użytkownika. Aby to umożliwić, zintegruj uwierzytelnianie Firebase, aby użytkownicy mogli logować się w aplikacji.
Być może zauważyłeś już przycisk awatara użytkownika w prawym górnym rogu ekranu głównego. Po jego kliknięciu otworzy się ekran, na którym użytkownicy mogą się zarejestrować lub zalogować, używając adresu e-mail i hasła.
Po zalogowaniu się użytkownika aplikacja musi przechowywać jego najważniejsze dane, przede wszystkim unikalny identyfikator użytkownika i wybraną nazwę użytkownika.
Włączanie uwierzytelniania Firebase
W konsoli Firebase swojego projektu otwórz sekcję Uwierzytelnianie i włącz Uwierzytelnianie Firebase. Następnie włącz dostawcę uwierzytelniania przy użyciu adresu e-mail i hasła.
Aby włączyć emulator uwierzytelniania Firebase, w lokalnym folderze projektu odszukaj plik firebase.json
i zaktualizuj go w ten sposób:
{
"emulators": {
"dataconnect": {
},
"auth": {
}
},
"dataconnect": {
"source": "dataconnect"
}
}
Aby zmiany zaczęły obowiązywać, musisz zatrzymać i ponownie uruchomić emulator Firebase.
Implementowanie modułu obsługi uwierzytelniania
W następnej sekcji zaimplementujesz logikę, która łączy uwierzytelnianie użytkownika z bazą danych. Polega to na utworzeniu modułu uwierzytelniania, który sprawdza, czy logowanie się zakończyło sukcesem.
Po uwierzytelnieniu użytkownika ten moduł obsługi automatycznie spowoduje utworzenie odpowiedniego konta w Twojej bazie danych.
W Xcode otwórz plik AuthenticationService.swift
i dodaj ten kod:
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
}
}
To ogólny moduł obsługi uwierzytelniania, który umożliwia użycie funkcji onSignUp
do zarejestrowania funkcji zamykania, która zostanie wywołana po zalogowaniu użytkownika.
W ramach tego zamknięcia możesz utworzyć nowe konto użytkownika w bazie danych. Zanim to zrobisz, musisz utworzyć mutację, która pozwoli Ci tworzyć i aktualizować nowych użytkowników w bazie danych.
Dodawanie do schematu elementu Użytkownik
Typ User
definiuje element użytkownika. Użytkownicy mogą wchodzić w interakcje z filmami, dodając do nich opinie lub dodając je do ulubionych.
W VS Code otwórz plik dataconnect/schema/schema.gql
i dodaj do niego tę definicję tabeli User
:
## 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)")
}
Definiowanie zapytania na potrzeby wstawiania lub aktualizowania użytkownika
W VS Code otwórz plik dataconnect/connector/mutations.gql
i dodaj mutację UpsertUser
:
mutation UpsertUser($username: String!) @auth(level: USER) {
user_upsert(
data: {
id_expr: "auth.uid"
username: $username
}
)
}
Tworzenie nowego użytkownika po zalogowaniu
W Xcode otwórz FriendlyFlixApp.swift
i dodaj do funkcji inicjującej ten kod:
@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 {
...
}
}
Ten kod używa funkcji upsertUserMutation
Firebase Data Connect, aby w przypadku każdego użytkownika, który zarejestruje się za pomocą uwierzytelniania Firebase, wstawiać nowego użytkownika (lub aktualizować istniejącego użytkownika o ten sam identyfikator).
Jak to działa
Aby sprawdzić, czy to działa, najpierw zarejestruj się w aplikacji na iOS:
- Jeśli jeszcze tego nie zrobiono, zatrzymaj i ponownie uruchom emulator Firebase, aby upewnić się, że emulator uwierzytelniania Firebase działa.
- W Xcode kliknij przycisk Uruchom, aby uruchomić aplikację w symulatorze iOS.
- Kliknij ikonę awatara w prawym górnym rogu ekranu.
- Przejdź do procesu rejestracji i zarejestruj się w aplikacji.
Następnie przeprowadź zapytanie do bazy danych, aby sprawdzić, czy aplikacja utworzyła nowe konto użytkownika:
- W VS Code otwórz
dataconnect/schema/schema.gql
i kliknij Read data (Czytaj dane) na elemencieUser
. - Spowoduje to utworzenie nowego pliku zapytań o nazwie
User_read.gql
. - Aby wyświetlić wszystkich użytkowników w tabeli użytkowników, kliknij Uruchom lokalnie.
- W panelu wykonywania usługi Data Connect powinieneś/powinnaś zobaczyć konto użytkownika, którego właśnie zarejestrowano.
9. Zarządzanie ulubionymi filmami
W tej sekcji tego Codelab zaimplementujesz interakcje z użytkownikiem w aplikacji do oceniania filmów, umożliwiając mu m.in. zarządzanie ulubionymi filmami. Filmy oznaczone jako ulubione będą wyświetlane w sekcji listy Do obejrzenia w aplikacji.
Ulepszenie schematu w celu obsługi ulubionych
Typ FavoriteMovie
to tabela złączeń, która obsługuje relacje wiele do wielu między użytkownikami a ich ulubionymi filmami. Każda tabela łączy User
z Movie
.
Skopiuj fragment kodu i wklej go w pliku dataconnect/schema/schema.gql
:
type FavoriteMovie
@table(name: "FavoriteMovies", singular: "favorite_movie", plural: "favorite_movies", key: ["user", "movie"]) {
## @ref is implicit
user: User!
movie: Movie!
}
Definiowanie modyfikacji służących do dodawania i usuwania ulubionych
Zanim aplikacja wyświetli ulubione filmy użytkownika, musi on wskazać, które są jego ulubionymi. Aby to zrobić, musisz najpierw dodać 2 mutacje: jedną, która oznacza film jako jeden z ulubionych użytkownika, i drugą, która usuwa go z ulubionych.
- W VS Code otwórz
mutations.gql
wdataconnect/connector/mutations.gql
- Aby obsługiwać dodawanie filmów do ulubionych, dodaj te mutacje:
## 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 })
}
Łączenie mutacji z interfejsem aplikacji
Użytkownicy mogą oznaczyć film jako ulubiony, klikając ikonę serca na ekranie z informacjami o filmie.
Aby połączyć utworzone przed chwilą mutacje z interfejsem aplikacji, w pliku MovieCardView
wprowadź te zmiany:
- Zaimportuj
FriendlyFlixSDK
i skonfiguruj oprogramowanie sprzęgające
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
...
}
- Zaimplementuj metodę
toggleFavourite
. Jest on wywoływany, gdy użytkownik kliknie ikonę serca wMovieCardView
:
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)
}
}
}
}
Spowoduje to zaktualizowanie stanu ulubionego filmu w bazie danych. Ostatnim krokiem jest sprawdzenie, czy stan interfejsu użytkownika jest odpowiedni.
Definiowanie zapytania służącego do sprawdzania, czy film jest oznaczony jako ulubiony
- W VS Code otwórz
queries.gql
wdataconnect/connector
. - Aby sprawdzić, czy film jest oznaczony jako ulubiony, dodaj to zapytanie:
query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) {
favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) {
movieId
}
}
- W Xcode utwórz instancję odwołania do zapytania
GetIfFavoritedMovie
i wdróż właściwość obliczeniową, która określa, czy film wyświetlany w tymMovieCardView
jest oznaczony jako ulubiony przez bieżącego użytkownika.
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
}
...
}
- Zaktualizuj kod w miejscu
toggleFavourite
, aby wykonywać zapytanie, gdy użytkownik kliknie przycisk. Dzięki temu właściwość obliczanaisFavourite
zawsze zwraca prawidłową wartość.
private func toggleFavourite() {
Task {
if isFavourite {
...
}
let _ = try await isFavouriteRef.execute()
}
}
Pobieranie ulubionych filmów
Ostatnim krokiem w przypadku tej funkcji jest pobranie ulubionych filmów użytkownika, aby mógł je zobaczyć na liście obejrzanych filmów.
- W VS Code otwórz
queries.gql
wdataconnect/connector/queries.gql
i wklej to zapytanie:
## 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
}
}
}
}
Lista ulubionych filmów użytkownika wyświetla się na ekranie LibraryScreen
. Ten ekran powinien wyświetlać dane tylko wtedy, gdy użytkownik jest zalogowany, więc najpierw połącz stan uwierzytelniania ekranu z funkcją AuthenticationService
aplikacji.
- Dodaj kod do mapy z
FavoriteMovieFavoriteMovies
doMovie
doMovie+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
}
}
- W Xcode otwórz
LibraryScreen
, a potem zaktualizujisSignedIn
w ten sposób:
struct LibraryScreen: View {
...
private var isSignedIn: Bool {
authenticationService.user != nil
}
}
- Następnie zaimportuj Firebase Data Connect i FriendlyFlixSDK oraz uzyskaj odwołanie do zapytania
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) ?? []
}
...
}
- Upewnij się, że zapytanie
watchListRef
jest wykonywane, gdy pojawia się widok:
extension LibraryScreen: View {
var body: some View {
...
MovieListSection(namespace: namespace, title: "Watch List", movies: watchList)
.onAppear {
Task {
try await watchListRef.execute()
}
...
Jak to działa
Możesz teraz uruchomić aplikację i wypróbować właśnie zaimplementowaną funkcję ulubionych. Warto pamiętać:
- Upewnij się, że emulator Firebase jest uruchomiony.
- Upewnij się, że dodałeś/dodałaś dane testowe dotyczące filmów i szczegółów filmów.
- Upewnij się, że jesteś zarejestrowany jako użytkownik.
- W Xcode kliknij przycisk Uruchom, aby uruchomić aplikację w symulatorze iOS.
- Po uruchomieniu aplikacji kliknij kartę filmu, aby wyświetlić jego szczegóły.
- Kliknij ikonę serca, aby oznaczyć film jako ulubiony. Serce powinno stać się pełne.
- Powtórz to w przypadku kilku filmów.
- Otwórz kartę Biblioteka. Powinna wyświetlić się lista wszystkich filmów oznaczonych jako ulubione.
10. Gratulacje
Gratulacje! Udało Ci się dodać Firebase Data Connect do aplikacji na iOS. Znasz już najważniejsze kroki wymagane do konfigurowania Data Connect, tworzenia zapytań i mutacji oraz obsługi uwierzytelniania użytkowników.
Opcjonalnie: wdrożenie w gałęzi produkcyjnej
Do tej pory aplikacja używała tylko emulatorów Firebase. Jeśli chcesz dowiedzieć się, jak wdrożyć tę aplikację w prawdziwym projekcie Firebase, przejdź do następnego kroku.
11. (Opcjonalnie) Wdróż aplikację
Dotychczas ta aplikacja była całkowicie lokalna, a wszystkie dane były przechowywane w Pakiecie emulatorów Firebase. W tej sekcji dowiesz się, jak skonfigurować projekt Firebase, aby aplikacja działała w produkcji.
Włączanie uwierzytelniania Firebase
- W konsoli Firebase otwórz sekcję Uwierzytelnianie i kliknij Rozpocznij.
- Otwórz kartę Metoda logowania .
- W sekcji dostawców własnych wybierz opcję Adres e-mail/hasło.
- Włącz dostawcę E-mail/hasło, a następnie kliknij Zapisz.
Włączanie Firebase Data Connect
Ważne: jeśli wdrażasz schemat w swoim projekcie po raz pierwszy, ten proces utworzy instancję Cloud SQL PostgreSQL, co może potrwać około 15 minut. Nie będzie można wdrożyć usługi, dopóki instancja Cloud SQL nie będzie gotowa i zintegrowana z Firebase Data Connect.
1. W interfejsie rozszerzenia Firebase Data Connect w VS Code kliknij Wdróż w środowisku produkcyjnym. 2. Może być konieczne sprawdzenie zmian w schemacie i zatwierdzenie potencjalnie szkodliwych modyfikacji. Pojawi się prośba o: – sprawdzenie zmian w schemacie za pomocą firebase dataconnect:sql:diff
– zastosowanie zmian za pomocą procesu firebase dataconnect:sql:migrate
Twoja instancja Cloud SQL for PostgreSQL zostanie zaktualizowana o ostateczny wdrożony schemat i dane. Stan możesz sprawdzać w konsoli Firebase.
Aby dodać dane do środowiska produkcyjnego, możesz teraz w panelu Firebase Data Connect kliknąć Uruchom (produkcja), tak jak w przypadku lokalnych emulatorów.
Zanim ponownie uruchomisz aplikację na iOS, sprawdź, czy łączy się z produkcyjną instancją projektu:
- Otwórz menu Produkt > Schemat > Edytuj schemat….
- W sekcji Uruchom odznacz argument
-useEmulator YES
.