1. Visão geral
Este codelab orienta você no processo de integração do Firebase Data Connect com um banco de dados do Cloud SQL para criar um app de avaliação de filmes para iOS usando o SwiftUI.
Você vai aprender a conectar seu aplicativo iOS a um banco de dados do Cloud SQL usando o Firebase Data Connect, permitindo a sincronização de dados perfeita para avaliações de filmes.
Ao final deste codelab, você terá um app iOS funcional que permite aos usuários navegar por filmes e marcá-los como favoritos, tudo com o suporte de um banco de dados do Cloud SQL usando o poder do Firebase Data Connect.
O que você vai aprender
Neste codelab, você vai aprender a:
- Configure o Firebase Data Connect usando o pacote de emuladores do Firebase para tempos de resposta rápidos.
- Projete um esquema de banco de dados usando o Data Connect e o GraphQL.
- Crie um SDK Swift typesafe com base no esquema do banco de dados e adicione-o a um aplicativo Swift.
- Implemente a autenticação de usuários e integre-a ao Firebase Data Connect para proteger os dados dos usuários.
- Recupere, atualize, exclua e gerencie dados no Cloud SQL usando consultas e mutações com tecnologia do GraphQL.
- (Opcional) Implante um serviço do Data Connect na produção.
Pré-requisitos
- A versão mais recente do Xcode
- O exemplo de código do codelab. Você vai fazer o download do exemplo de código em uma das primeiras etapas do codelab.
2. Configurar o projeto de amostra
Criar um projeto do Firebase
- Faça login no console do Firebase usando sua Conta do Google.
- Clique no botão para criar um projeto e insira um nome (por exemplo,
Friendly Flix
).
- Clique em Continuar.
- Se solicitado, leia e aceite os Termos do Firebase e clique em Continuar.
- (Opcional) Ative a assistência de IA no console do Firebase (chamada de "Gemini no Firebase").
- Neste codelab, você não precisa do Google Analytics. Portanto, desative a opção do Google Analytics.
- Clique em Criar projeto, aguarde o provisionamento e clique em Continuar.
Fazer o download do código
Execute o comando a seguir para clonar o código de amostra deste codelab. Isso vai criar um diretório chamado codelab-dataconnect-ios
na sua máquina:
git clone https://github.com/FirebaseExtended/codelab-dataconnect-ios`
Se você não tiver o git na sua máquina, também poderá fazer o download do código diretamente do GitHub.
Adicionar configuração do Firebase
O SDK do Firebase usa um arquivo de configuração para se conectar ao seu projeto do Firebase. Em plataformas Apple, esse arquivo é chamado de GoogleServices-Info.plist
. Nesta etapa, você vai baixar o arquivo de configuração e adicioná-lo ao projeto do Xcode.
- No console do Firebase, selecione Visão geral do projeto no menu de navegação à esquerda.
- Clique no botão iOS+ para selecionar a plataforma. Quando o ID do pacote da Apple for solicitado, use
com.google.firebase.samples.FriendlyFlix
. - Clique em Registrar app e siga as instruções para fazer o download do arquivo
GoogleServices-Info.plist
. - Mova o arquivo baixado para o diretório
start/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/
do código que você acabou de baixar, substituindo o arquivoGoogleServices-Info.plist
atual. - Em seguida, clique em Próxima algumas vezes para concluir o projeto de configuração no console do Firebase. Não é necessário adicionar o SDK ao app, já que isso já foi feito no projeto inicial.
- Por fim, clique em Continuar para o console para concluir o processo de configuração.
3. Configurar o Data Connect
Instalação
Instalação automática
Execute o seguinte comando no diretório codelab-dataconnect-ios/FriendlyFlix
:
curl -sL https://firebase.tools/dataconnect | bash
Esse script tenta configurar o ambiente de desenvolvimento para você e iniciar um IDE baseado em navegador. Esse ambiente de desenvolvimento integrado oferece ferramentas, incluindo uma extensão do VS Code pré-agrupada, para ajudar você a gerenciar seu esquema e definir consultas e mutações a serem usadas no aplicativo, além de gerar SDKs fortemente tipados.
Depois de executar o script, o VS Code vai abrir automaticamente.
Depois de fazer isso uma vez, você pode iniciar o VS Code executando-o no diretório local:
code .
Instalação manual
- Instalar o Visual Studio Code
- Instale o Node.js.
- No VS Code, abra o diretório
codelab-dataconnect-ios/FriendlyFlix
. - Instale a extensão do Firebase Data Connect no Visual Studio Code Marketplace.
Inicializar o Data Connect no projeto
No painel à esquerda, clique no ícone do Firebase para abrir a interface da extensão Data Connect VS Code.
- Clique no botão Fazer login com o Google. Uma janela do navegador será aberta. Siga as instruções para fazer login na extensão com sua Conta do Google.
- Clique no botão Conectar um projeto do Firebase e selecione o projeto que você criou antes no console.
- Clique no botão Executar firebase init e siga as etapas no terminal integrado.
Configurar a geração do SDK
Depois de clicar no botão Executar firebase init, a extensão Firebase Data Connect vai inicializar um diretório dataconnect
para você.
No VS Code, abra o arquivo dataconnect/connector/connector.yaml
para encontrar a configuração padrão.
Atualize a configuração e use as seguintes configurações para garantir que o código gerado funcione com este codelab. Especificamente, verifique se connectorId
está definido como friendly-flix
e o pacote Swift como FriendlyFlixSDK
.
connectorId: "friendly-flix"
generate:
swiftSdk:
outputDir: "../../app"
package: "FriendlyFlixSDK"
observablePublisher: observableMacro
Confira o que essas configurações significam:
connectorId
: um nome exclusivo para o conector.outputDir
: caminho em que o SDK do Data Connect gerado será armazenado. Esse caminho é relativo ao diretório que contém o arquivoconnector.yaml
.package
: o nome do pacote a ser usado para o pacote Swift gerado.
Depois de salvar esse arquivo, o Firebase Data Connect vai gerar um pacote Swift chamado FriendlyFlixSDK
e colocá-lo ao lado da pasta do projeto FriendlyFlix
.
Iniciar os emuladores do Firebase
No VS Code, mude para a visualização do Firebase e clique no botão Iniciar emuladores.
Isso vai iniciar o Firebase Emulator no terminal integrado. O resultado será semelhante a este:
npx -y firebase-tools@latest emulators:start --project <your-project-id>
Adicionar o pacote gerado ao seu app Swift
- Abrir
FriendlyFlix/app/FriendlyFlix/FriendlyFlix.xcodeproj
no Xcode - Selecione Arquivo > Adicionar dependências de pacote…
- Clique em Adicionar local... e adicione o pacote
FriendlyFlixSDK
da pastaFriendlyFlix/app
. - Aguarde o Xcode resolver as dependências do pacote.
- Na caixa de diálogo Escolher produtos de pacote para FriendlyFlixSDK, selecione
FriendlyFlix
como destino e clique em Adicionar pacote.
Configurar o app iOS para usar o emulador local
- Abra
FriendlyFlixApp.swift
. Você pode pressionar CMD + Shift + O para abrir a caixa de diálogo Abertura rápida e digitar "FriendlyFlixApp" para encontrar o arquivo rapidamente. - Importar o Firebase, o Firebase Auth, o Firebase Data Connect e o SDK gerado para seu esquema
- No inicializador, configure o Firebase.
- Verifique se o DataConnect e o Firebase Auth estão usando o emulador local.
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()
}
...
}
- Selecione um simulador do iOS no menu suspenso Destino.
- Pressione CMD+R ou clique no botão Run no Xcode para executar o app em um simulador.
4. Definir o esquema e pré-preencher o banco de dados
Nesta seção, você vai definir a estrutura e as relações entre as principais entidades do aplicativo de filmes em um esquema. Entidades como Movie
, MovieMetaData
e outras são mapeadas para tabelas de banco de dados, com relacionamentos estabelecidos usando o Firebase Data Connect e diretivas de esquema GraphQL.
Entidades e relacionamentos principais
O modelo de dados para este app de rastreamento de filmes consiste em várias entidades que você vai criar ao longo deste codelab. Primeiro, você vai criar as entidades principais e, à medida que implementar mais recursos, vai adicionar as entidades necessárias para eles.
Nesta etapa, você vai criar os tipos Movie
e MovieMetadata
.
Filme
O tipo Movie
define a estrutura principal de uma entidade de filme, incluindo campos como title
, genre
, releaseYear
e rating
.
No VS Code, adicione a definição do tipo Movie
a 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
O tipo MovieMetadata
estabelece uma relação de um para um com o tipo Movie
. Ele inclui outros dados, como o diretor do filme.
Adicione a definição da tabela MovieMetadata
ao arquivo dataconnect/schema/schema.gql
:
type MovieMetadata @table {
movie: Movie! @ref
director: String
}
Campos e padrões gerados automaticamente
O esquema usa expressões como @default(expr: "uuidV4()")
para gerar automaticamente IDs e carimbos de data/hora exclusivos. Por exemplo, o campo id
no tipo Movie
é preenchido automaticamente com um UUID quando um novo registro é criado.
Inserir dados simulados para filmes e metadados de filmes
Com o esquema definido, agora é possível pré-preencher o banco de dados com dados simulados para teste.
- No Finder, copie
finish/FriendlyFlix/dataconnect/moviedata_insert.gql
para a pastastart/FriendlyFlix/dataconnect
. - No VS Code, abra
dataconnect/moviedata_insert.gql
. - Verifique se os emuladores na extensão do Firebase Data Connect estão em execução.
- Você vai encontrar um botão Executar (local) na parte de cima do arquivo. Clique aqui para inserir os dados simulados de filmes no banco de dados.
- Verifique o terminal Execução do Data Connect para confirmar se os dados foram adicionados corretamente.
Com os dados no lugar, siga para a próxima etapa e saiba como criar consultas no Data Connect.
5. Recuperar e mostrar filmes
Nesta seção, você vai implementar um recurso para mostrar uma lista de filmes.
Primeiro, você vai aprender a criar uma consulta que recupera todos os filmes da tabela movies
. O Firebase Data Connect gera código para um SDK type-safe que pode ser usado para executar a consulta e mostrar os filmes recuperados na interface do app.
Definir a consulta ListMovies
As consultas no Firebase Data Connect são escritas em GraphQL, permitindo que você especifique quais campos buscar. No FriendlyFlix, as telas que mostram filmes exigem os seguintes campos: title
, description
, releaseYear
, rating
e imageUrl
. Além disso, como este é um app SwiftUI, você vai precisar do id
para ajudar com a identidade da visualização do SwiftUI.
No VS Code, abra o arquivo dataconnect/connector/queries.gql
e adicione a consulta ListMovies
:
query ListMovies @auth(level: PUBLIC) {
movies {
id
title
imageUrl
releaseYear
genre
rating
tags
description
}
}
Para testar a nova consulta, clique no botão Executar (local) para executar a consulta no banco de dados local. A lista de filmes do banco de dados vai aparecer na seção Resultados do terminal de execução do Data Connect.
Conectar a consulta ListMovies à tela inicial do app
Agora que você testou a consulta no emulador do Data Connect, é possível chamar a consulta de dentro do app.
Quando você salva queries.gql
, o Firebase Data Connect gera o código correspondente à consulta ListMovies
no pacote FriendlyFlixSDK
.
No Xcode, abra Movie+DataConnect.swift
e adicione o seguinte código para mapear de ListMoviesQuery.Data.Movie
para 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
}
}
Abra o arquivo HomeScreen.swift
e atualize-o usando o seguinte snippet de código.
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) ?? []
}
...
}
A consulta |
Executar o app
No Xcode, clique no botão Run para iniciar o app no simulador do iOS.
Quando o app for iniciado, você vai ver uma tela como esta:
Você vai notar que todas as áreas do app (seção principal, principais filmes e lista de exibição) mostram a mesma lista. Isso acontece porque você está usando a mesma consulta para todas essas visualizações. Nas próximas seções, você vai implementar consultas personalizadas. |
6. Mostrar o herói e os principais filmes
Nesta etapa, você vai atualizar a forma como os filmes são mostrados na seção principal, que é o carrossel em destaque na parte de cima da tela inicial, e também na seção de filmes mais assistidos abaixo.
No momento, a consulta "ListMovies" recupera todos os filmes. Para otimizar a exibição dessas seções, você vai limitar o número de filmes que cada consulta retorna. A implementação atual da consulta ListMovies
ainda não oferece suporte integrado para limitar os resultados. Adicionar suporte para limitar e ordenar é algo que você vai fazer nesta seção.
Melhorar a consulta ListMovies
Abra queries.gql
e atualize ListMovies
da seguinte maneira para adicionar suporte à ordenação e limitação:
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
}
}
Isso permite limitar o número de filmes retornados pela consulta e ordenar o conjunto de resultados por classificação e ano de lançamento.
Depois de salvar esse arquivo, o Firebase Data Connect vai gerar novamente o código em FriendlyFlixSDK
automaticamente. Na próxima etapa, você vai atualizar o código em HomeScreen.swift
para usar esses recursos adicionais.
Usar a consulta aprimorada na interface
Volte para o Xcode e faça as mudanças necessárias em HomeScreen.swift
.
Primeiro, atualize heroMoviesRef
para buscar os três filmes lançados mais recentemente:
struct HomeScreen {
...
init() {
heroMoviesRef = connector.listMoviesQuery
.ref { optionalVars in
optionalVars.limit = 3
optionalVars.orderByReleaseYear = .DESC
}
}
}
Em seguida, configure outra referência de consulta para os principais filmes e defina o filtro para os cinco filmes mais bem avaliados:
struct HomeScreen {
...
let topMoviesRef: QueryRefObservation<ListMoviesQuery.Data, ListMoviesQuery.Variables>
init() {
heroMoviesRef = ...
topMoviesRef = connector.listMoviesQuery
.ref { optionalVars in
optionalVars.limit = 5
optionalVars.orderByRating = .DESC
}
}
}
Por fim, atualize a propriedade computada que conecta o resultado dessa consulta à interface:
extension HomeScreen {
...
private var topMovies: [Movie] {
topMoviesRef.data?.movies.map(Movie.init) ?? []
}
}
Veja na prática
Execute o app novamente para conferir os três filmes mais recentes na seção principal e os cinco filmes mais bem avaliados na seção "Melhores filmes":
7. Mostrar detalhes de filmes e atores
O usuário agora pode navegar pelos filmes. Ao tocar em um card de filme, alguns detalhes sobre ele são mostrados, mas você pode ter notado que eles não têm muito... detalhe!
Isso porque só buscamos os detalhes necessários para renderizar a seção principal e a seção de melhores filmes: título, uma breve descrição e o URL da imagem.
Na página de detalhes do filme, vamos mostrar mais informações sobre ele. Nesta seção, você vai melhorar o app para que ele possa mostrar os atores do filme e as avaliações na página de detalhes.
Para isso, você precisa fazer algumas coisas:
- Melhorar o esquema para oferecer suporte a atores e avaliações de filmes
- Escrever consultas do Firebase Data Connect para buscar detalhes sobre um filme específico
- Mostrando os resultados na tela de detalhes do filme
Melhorar o esquema
No VS Code, abra dataconnect/schema/schema.gql
e adicione as definições de esquema para Actor
e 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"
}
Adicionar dados simulados para atores
Com o esquema atualizado, agora é possível preencher o banco de dados com mais dados simulados para teste.
- No Finder, copie
finish/FriendlyFlix/dataconnect/moviededetails_insert.gql
para a pastastart/FriendlyFlix/dataconnect
. - No VS Code, abra
dataconnect/moviededetails_insert.gql
. - Verifique se os emuladores na extensão do Firebase Data Connect estão em execução.
- Você vai encontrar um botão Executar (local) na parte de cima do arquivo. Clique aqui para inserir os dados simulados de filmes no banco de dados.
- Verifique o terminal de execução do Data Connect para confirmar se os dados foram adicionados corretamente.
Com os dados no lugar, siga para a próxima etapa e defina a consulta para buscar os detalhes do filme.
Definir a consulta GetMovieById
No VS Code, abra o arquivo dataconnect/connector/queries.gql
e adicione a consulta 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
}
}
}
Conectar a consulta GetMovieById à MovieDetailsView
No Xcode, abra o arquivo MovieDetailsView.swift
e atualize a propriedade computada movieDetails
para que ela corresponda ao seguinte código:
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
}
}
Executar o app
No Xcode, clique no botão Run para iniciar o app no simulador do iOS.
Quando o app for iniciado, toque em um card de filme para mostrar os detalhes. Ele será parecido com o seguinte:
8. Implementar a autenticação do usuário
No momento, o app apresenta informações não personalizadas sobre filmes e atores. Nas etapas a seguir, você vai implementar recursos que associam dados ao usuário conectado. Primeiro, permita que os usuários adicionem filmes à lista de interesses pessoal.
Antes de implementar o recurso de lista de observação, você precisa estabelecer a identidade do usuário. Para isso, você vai integrar o Firebase Authentication, permitindo que os usuários façam login no app.
Talvez você já tenha visto o botão do avatar do usuário no canto superior direito da tela inicial. Ao tocar nessa opção, você vai acessar uma tela em que os usuários podem se inscrever ou fazer login usando e-mail e senha.
Depois que um usuário fizer login, seu app precisará armazenar os detalhes essenciais dele, principalmente o ID de usuário exclusivo e o nome de usuário escolhido.
Ativar o Firebase Authentication
No console do Firebase do seu projeto, acesse a seção "Autenticação" e ative o Firebase Authentication. Em seguida, ative o provedor de autenticação por e-mail/senha.
Na pasta do projeto local, encontre firebase.json
e atualize da seguinte maneira para ativar o emulador do Firebase Authentication.
{
"emulators": {
"dataconnect": {
},
"auth": {
}
},
"dataconnect": {
"source": "dataconnect"
}
}
Depois disso, pare e reinicie o emulador do Firebase para que a mudança entre em vigor.
Implementar um gerenciador de autenticação
Na seção a seguir, você vai implementar a lógica que conecta a autenticação de usuários ao seu banco de dados. Isso envolve a criação de um gerenciador de autenticação que detecta logins bem-sucedidos.
Depois que um usuário é autenticado, esse manipulador aciona automaticamente a criação da conta correspondente no banco de dados.
No Xcode, abra o arquivo AuthenticationService.swift
e adicione o seguinte código:
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
}
}
Esse é um gerenciador de autenticação genérico que permite usar onSignUp
para registrar um fechamento que será chamado quando o usuário fizer login.
Dentro desse fechamento, você pode criar uma nova conta de usuário no banco de dados. Mas, antes disso, você precisa criar uma mutação que permita criar ou atualizar novos usuários no banco de dados.
Adicionar uma entidade de usuário ao esquema
O tipo User
define uma entidade de usuário. Os usuários podem interagir com filmes deixando avaliações ou marcando como favoritos.
No VS Code, abra o arquivo dataconnect/schema/schema.gql
e adicione a seguinte definição de tabela 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)")
}
Definir uma mutação para inserir ou atualizar um usuário
No VS Code, abra o arquivo dataconnect/connector/mutations.gql
e adicione a mutação UpsertUser
:
mutation UpsertUser($username: String!) @auth(level: USER) {
user_upsert(
data: {
id_expr: "auth.uid"
username: $username
}
)
}
Criar um usuário após fazer login
No Xcode, abra FriendlyFlixApp.swift
e adicione o seguinte código ao inicializador:
@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 {
...
}
}
Esse código usa o upsertUserMutation
do Firebase Data Connect gerado para você inserir um novo usuário (ou atualizar um usuário existente com o mesmo ID) sempre que um usuário se inscrever com sucesso usando o Firebase Authentication.
Veja na prática
Para verificar se isso funciona, primeiro inscreva-se no app iOS:
- Se não tiver feito isso, pare e reinicie o emulador do Firebase para garantir que o emulador do Firebase Authentication esteja em execução.
- No Xcode, clique no botão Run para iniciar o app no simulador do iOS.
- Clique no ícone do avatar no canto superior direito da tela.
- Mude para o fluxo de inscrição e inscreva-se no app.
Em seguida, consulte o banco de dados para verificar se o app criou uma nova conta de usuário para o usuário:
- No VS Code, abra
dataconnect/schema/schema.gql
e clique em Ler dados na entidadeUser
. - Isso vai criar um novo arquivo de consulta chamado
User_read.gql
. - Clique em Executar localmente para ver todos os usuários na tabela de usuários.
- No painel "Execução da conexão de dados", agora você vai encontrar uma conta do usuário que acabou de se inscrever com
9. Gerenciar filmes favoritos
Nesta seção do codelab, você vai implementar interações do usuário no app de avaliação de filmes, especificamente permitindo que os usuários gerenciem os filmes favoritos. Os filmes marcados como favoritos aparecem na seção "Lista de interesses" do app.
Melhorar o esquema para oferecer suporte aos favoritos
O tipo FavoriteMovie
é uma tabela de junção que processa relações de muitos para muitos entre usuários e seus filmes favoritos. Cada tabela vincula um User
a um Movie
.
Copie e cole o snippet de código no arquivo 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!
}
Definir mutações para adicionar e remover favoritos
Antes que o app possa mostrar os filmes favoritos do usuário, ele precisa indicar quais são os favoritos. Para isso, primeiro adicione duas mutações para marcar um filme como um dos favoritos do usuário ou removê-lo dos favoritos novamente, respectivamente.
- No VS Code, abra
mutations.gql
emdataconnect/connector/mutations.gql
. - Adicione as seguintes mutações para processar a ação de adicionar filmes aos favoritos:
## 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 })
}
Conectar as mutações à interface do seu app
Os usuários podem marcar um filme como favorito clicando no ícone de coração na tela de detalhes dele.
Para conectar as mutações que você acabou de criar à interface do app, faça as seguintes mudanças em MovieCardView
:
- Importar o
FriendlyFlixSDK
e configurar o conector
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
...
}
- Implemente o método
toggleFavourite
. Ele será chamado sempre que o usuário tocar no ícone de coração noMovieCardView
:
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)
}
}
}
}
Isso vai atualizar o estado de favorito do filme atual no banco de dados. Uma última etapa que está faltando é garantir que o estado da UI seja refletido adequadamente.
Definir uma consulta para descobrir se um filme foi marcado como favorito
- No VS Code, abra
queries.gql
emdataconnect/connector
. - Adicione a seguinte consulta para verificar se um filme está marcado como favorito:
query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) {
favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) {
movieId
}
}
- No Xcode, crie uma instância de referência à consulta
GetIfFavoritedMovie
e implemente a propriedade calculada que determina se o filme mostrado noMovieCardView
está marcado como favorito para o usuário atual.
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
}
...
}
- Atualize o código em
toggleFavourite
para executar a consulta sempre que o usuário tocar no botão. Isso garante que a propriedade computadaisFavourite
sempre retorne o valor correto.
private func toggleFavourite() {
Task {
if isFavourite {
...
}
let _ = try await isFavouriteRef.execute()
}
}
Buscar filmes favoritos
Como etapa final desse recurso, você vai implementar a busca dos filmes favoritos do usuário para que eles possam ser exibidos na lista de exibição.
- No VS Code, abra
queries.gql
emdataconnect/connector/queries.gql
e cole a seguinte consulta:
## 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
}
}
}
}
A lista de filmes favoritos do usuário é exibida no LibraryScreen
. Essa tela só vai mostrar dados se o usuário estiver conectado. Portanto, primeiro conecte o estado de autenticação da tela ao AuthenticationService
do app.
- Adicione código para mapear de um
FavoriteMovieFavoriteMovies
para umMovie
paraMovie+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
}
}
- No Xcode, abra
LibraryScreen
e atualizeisSignedIn
da seguinte maneira:
struct LibraryScreen: View {
...
private var isSignedIn: Bool {
authenticationService.user != nil
}
}
- Em seguida, importe o Firebase Data Connect e o FriendlyFlixSDK e receba uma referência à consulta
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) ?? []
}
...
}
- Verifique se a consulta
watchListRef
é executada quando a visualização aparece:
extension LibraryScreen: View {
var body: some View {
...
MovieListSection(namespace: namespace, title: "Watch List", movies: watchList)
.onAppear {
Task {
try await watchListRef.execute()
}
...
Veja na prática
Agora você pode executar o app e testar o recurso de favoritos que acabou de implementar. Alguns pontos importantes:
- Verifique se o emulador do Firebase está em execução
- Verifique se você adicionou dados simulados para os filmes e os detalhes deles.
- Verifique se você se inscreveu como usuário
- No Xcode, clique no botão Run para iniciar o app no simulador do iOS.
- Quando o app for iniciado, toque em um card de filme para mostrar os detalhes.
- Toque no ícone de coração para marcar o filme como favorito. O coração vai ficar sólido.
- Repita isso para alguns filmes.
- Acesse a guia "Biblioteca". Agora você vai ver uma lista de todos os filmes marcados como favoritos.
10. Parabéns
Parabéns! Você adicionou o Firebase Data Connect a um app iOS. Agora você conhece as principais etapas necessárias para configurar o Data Connect, criar consultas e mutações e processar a autenticação do usuário.
Opcional: implante na produção
Até agora, este app só usou os emuladores do Firebase. Se quiser saber como implantar esse app em um projeto real do Firebase, continue para a próxima etapa.
11. (Opcional) Implante o app
Até agora, este app foi totalmente local. Todos os dados estão contidos no Pacote de emuladores do Firebase. Nesta seção, você vai aprender a configurar seu projeto do Firebase para que o app funcione em produção.
Ativar o Firebase Authentication
- No console do Firebase, acesse a seção Autenticação e clique em Começar.
- Acesse a guia Método de login .
- Selecione a opção "E-mail/senha" na seção de provedores nativos.
- Ative o provedor de e-mail/senha e clique em Salvar.
Ativar o Firebase Data Connect
Importante: se esta for a primeira vez que você implanta um esquema no seu projeto, esse processo vai criar uma instância do Cloud SQL PostgreSQL, o que pode levar cerca de 15 minutos. Não será possível fazer a implantação até que a instância do Cloud SQL esteja pronta e integrada ao Firebase Data Connect.
1. Na interface da extensão do Firebase Data Connect no VS Code, clique em Implantar na produção. 2. Talvez seja necessário analisar as mudanças de esquema e aprovar modificações potencialmente destrutivas. Você vai precisar: - Revisar as mudanças de esquema usando firebase dataconnect:sql:diff
- Quando estiver tudo pronto, aplique as mudanças usando o fluxo iniciado por firebase dataconnect:sql:migrate
Sua instância do Cloud SQL para PostgreSQL será atualizada com o esquema e os dados finais implantados. Você pode monitorar o status no console do Firebase.
Agora você pode clicar em "Executar (produção)" no painel "Firebase Data Connect", assim como fez com os emuladores locais, para adicionar dados ao ambiente de produção.
Antes de executar o app iOS novamente, verifique se ele está conectado à instância de produção do projeto:
- Abra o menu Produto > Esquema > Editar esquema….
- Na seção Executar, desmarque o argumento de inicialização
-useEmulator YES
.