1. Обзор
Эта лаборатория кода проведет вас через процесс интеграции Firebase Data Connect с базой данных Cloud SQL для создания приложения для просмотра фильмов для iOS с использованием SwiftUI.
Вы узнаете, как подключить свое приложение iOS к базе данных Cloud SQL с помощью Firebase Data Connect, что обеспечивает беспрепятственную синхронизацию данных для обзоров фильмов.
К концу этой лабораторной работы у вас будет функциональное приложение для iOS, которое позволит пользователям просматривать фильмы и отмечать их как избранные, и все это на базе базы данных Cloud SQL с использованием возможностей Firebase Data Connect.
Что вы узнаете
Эта кодовая лаборатория научит вас:
- Настройте Firebase Data Connect с помощью пакета эмулятора Firebase, чтобы сократить время обработки.
- Спроектируйте схему базы данных с помощью Data Connect и GraphQL .
- Создайте типобезопасный Swift SDK на основе схемы базы данных и добавьте его в приложение Swift.
- Внедрите аутентификацию пользователей и интегрируйте ее с Firebase Data Connect, чтобы защитить данные ваших пользователей.
- Получайте, обновляйте, удаляйте данные в Cloud SQL и управляйте ими с помощью запросов и мутаций на базе GraphQL.
- (Необязательно) Разверните службу Data Connect в рабочей среде.
Предварительные условия
- Последняя версия Xcode
- Пример кода Codelab. Вы загрузите пример кода на одном из первых шагов лаборатории кода.
2. Настройте образец проекта
Создать проект Firebase
- Войдите в консоль Firebase под своей учетной записью Google.
- В консоли Firebase нажмите «Создать проект Firebase» .
- Введите имя своего проекта Firebase (например, «Friendly Flix») и нажмите «Продолжить» .
- Вас могут попросить включить поддержку искусственного интеллекта для вашего проекта Firebase. Для целей этой лаборатории ваш выбор не имеет значения.
- Вас могут попросить включить Google Analytics. Для целей данной лаборатории ваш выбор не имеет значения.
- Примерно через минуту ваш проект Firebase будет готов. Нажмите Продолжить .
Загрузите код
Выполните следующую команду, чтобы клонировать пример кода для этой лаборатории кода. На вашем компьютере будет создан каталог с именем codelab-dataconnect-ios
:
git clone https://github.com/FirebaseExtended/codelab-dataconnect-ios`
Если на вашем компьютере нет git, вы также можете загрузить код прямо с GitHub.
Добавить конфигурацию Firebase
Firebase SDK использует файл конфигурации для подключения к вашему проекту Firebase. На платформах Apple этот файл называется GoogleServices-Info.plist
. На этом этапе вы загрузите файл конфигурации и добавите его в свой проект Xcode.
- В консоли Firebase выберите «Обзор проекта» на левой панели навигации.
- Нажмите кнопку iOS+ , чтобы выбрать платформу. При запросе идентификатора пакета Apple используйте
com.google.firebase.samples.FriendlyFlix
- Нажмите «Зарегистрировать приложение» и следуйте инструкциям, чтобы загрузить файл
GoogleServices-Info.plist
. - Переместите загруженный файл в каталог
start/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/
только что загруженного кода, заменив существующий файлGoogleServices-Info.plist
. - Затем несколько раз нажмите «Далее» , чтобы завершить проект установки в консоли Firebase (вам не нужно добавлять SDK в приложение, поскольку об этом уже позаботились за вас в стартовом проекте).
- Наконец, нажмите «Продолжить работу с консолью» , чтобы завершить процесс установки.
3. Настройте подключение к данным.
Установка
Автоматическая установка
Выполните следующую команду в каталоге codelab-dataconnect-ios/FriendlyFlix
:
curl -sL https://firebase.tools/dataconnect | bash
Этот сценарий пытается настроить для вас среду разработки и запустить IDE на основе браузера. Эта IDE предоставляет инструменты, в том числе предварительно связанное расширение VS Code, которые помогут вам управлять схемой, определять запросы и мутации, которые будут использоваться в вашем приложении, а также генерировать строго типизированные SDK.
После запуска сценария VS Code должен открыться автоматически.
Сделав это один раз, вы можете запустить VS Code, запустив VS Code в локальном каталоге:
code .
Ручная установка
- Установить код Visual Studio
- Установите Node.js
- В VS Code откройте каталог
codelab-dataconnect-ios/FriendlyFlix
. - Установите расширение Firebase Data Connect из Visual Studio Code Marketplace .
Инициализируйте Data Connect в проекте
На левой панели щелкните значок Firebase, чтобы открыть пользовательский интерфейс расширения Data Connect VS Code.
- Нажмите кнопку «Войти через Google» . Откроется окно браузера; следуйте инструкциям, чтобы войти в расширение с помощью своей учетной записи Google.
- Нажмите кнопку «Подключить проект Firebase» и выберите в консоли проект, который вы создали ранее.
- Нажмите кнопку «Запустить инициализацию Firebase» и следуйте инструкциям во встроенном терминале.
Настройка генерации SDK
После того, как вы нажмете кнопку «Запустить инициализацию Firebase» , расширение Firebase Data Connect должно инициализировать для вас каталог dataconnect
.
В VS Code откройте файл dataconnect/connector/connector.yaml
, и вы найдете конфигурацию по умолчанию.
Обновите конфигурацию и используйте следующие настройки, чтобы убедиться, что сгенерированный код работает с этой лабораторией кода. В частности, убедитесь, что для connectorId
установлено значение friendly-flix
, а для пакета Swift — FriendlyFlixSDK
.
connectorId: "friendly-flix"
generate:
swiftSdk:
outputDir: "../../app"
package: "FriendlyFlixSDK"
observablePublisher: observableMacro
Вот что означают эти настройки:
-
connectorId
— уникальное имя для этого соединителя. -
outputDir
— путь, по которому будет храниться созданный Data Connect SDK. Этот путь указан относительно каталога, содержащего файлconnector.yaml
. -
package
— имя пакета, которое будет использоваться для сгенерированного пакета Swift.
Как только вы сохраните этот файл, Firebase Data Connect сгенерирует для вас пакет Swift с именем FriendlyFlixSDK
и поместит его рядом с папкой проекта FriendlyFlix
.
Запустите эмуляторы Firebase
В VS Code переключитесь на представление Firebase и нажмите кнопку «Запустить эмуляторы» .
Это запустит эмулятор Firebase во встроенном терминале. Вывод должен выглядеть так:
npx -y firebase-tools@latest emulators:start --project <your-project-id>
Добавьте сгенерированный пакет в свое приложение Swift.
- Откройте
FriendlyFlix/app/FriendlyFlix/FriendlyFlix.xcodeproj
в Xcode. - Выберите «Файл» > «Добавить зависимости пакета…».
- Нажмите «Добавить локальный...» , затем добавьте пакет
FriendlyFlixSDK
из папкиFriendlyFlix/app
- Подождите, пока Xcode разрешит зависимости пакета.
- В диалоговом окне «Выбор продуктов пакета для FriendlyFlixSDK» выберите
FriendlyFlix
в качестве цели и нажмите «Добавить пакет» .
Настройте приложение iOS для использования локального эмулятора.
- Откройте
FriendlyFlixApp.swift
. (Вы можете нажать CMD + Shift + O, чтобы открыть диалоговое окно быстрого открытия , а затем ввести «FriendlyFlixApp», чтобы быстро найти файл) - Импортируйте Firebase, Firebase Auth, Firebase Data Connect и созданный SDK для вашей схемы.
- В инициализаторе настройте Firebase.
- Убедитесь, что DataConnect и Firebase Auth используют локальный эмулятор.
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()
}
...
}
- Выберите симулятор iOS в раскрывающемся списке «Назначение» .
- Нажмите CMD+R (или нажмите кнопку « Выполнить ») в Xcode, чтобы запустить приложение в симуляторе.
4. Определите схему и предварительно заполните базу данных.
В этом разделе вы определите структуру и отношения между ключевыми объектами приложения фильма в схеме. Такие сущности, как Movie
, MovieMetaData
и другие, сопоставляются с таблицами базы данных, а отношения устанавливаются с помощью Firebase Data Connect и директив схемы GraphQL.
Основные сущности и отношения
Модель данных для этого приложения для отслеживания фильмов состоит из нескольких объектов, которые вы создадите в ходе этой лаборатории кода. Сначала вы создадите основные сущности, а по мере реализации все большего количества функций — будете добавлять сущности, необходимые для этих функций.
На этом этапе вы создадите типы Movie
и MovieMetadata
.
Фильм
Тип Movie
определяет основную структуру объекта фильма, включая такие поля, как title
, genre
, releaseYear
и rating
.
В VS Code добавьте определение типа Movie
в 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
устанавливает связь «один к одному» с типом Movie
. Он включает в себя дополнительные данные, такие как режиссер фильма.
Добавьте определение таблицы MovieMetadata
в файл dataconnect/schema/schema.gql
:
type MovieMetadata @table {
movie: Movie! @ref
director: String
}
Автоматически сгенерированные поля и значения по умолчанию
Схема использует такие выражения, как @default(expr: "uuidV4()")
для автоматического создания уникальных идентификаторов и временных меток. Например, поле id
в типе Movie
автоматически заполняется UUID при создании новой записи.
Вставка макетов данных для фильмов и метаданных фильмов
Определив схему, вы можете предварительно заполнить базу данных макетными данными для тестирования.
- В Finder скопируйте
finish/FriendlyFlix/dataconnect/moviedata_insert.gql
в папкуstart/FriendlyFlix/dataconnect
. - В VS Code откройте
dataconnect/moviedata_insert.gql
. - Убедитесь, что эмуляторы в расширении Firebase Data Connect работают.
- В верхней части файла вы должны увидеть кнопку «Выполнить» (локальную) . Нажмите эту кнопку, чтобы вставить данные макета фильма в вашу базу данных.
- Проверьте терминал Data Connect Execution, чтобы убедиться, что данные были успешно добавлены.
Имея данные, перейдите к следующему шагу, чтобы узнать, как создавать запросы в Data Connect.
5. Получение и отображение фильмов
В этом разделе вы реализуете функцию отображения списка фильмов.
Сначала вы узнаете, как создать запрос, извлекающий все фильмы из таблицы movies
. Firebase Data Connect генерирует код для типобезопасного SDK, который затем можно использовать для выполнения запроса и отображения полученных фильмов в пользовательском интерфейсе вашего приложения.
Определите запрос ListMovies
Запросы в Firebase Data Connect написаны на GraphQL, что позволяет вам указать, какие поля следует получать. В FriendlyFlix на экранах, на которых отображаются фильмы, требуются следующие поля: title
, description
, releaseYear
, rating
и imageUrl
. Кроме того, поскольку это приложение SwiftUI, вам понадобится id
, чтобы помочь с идентификацией представления SwiftUI.
В VS Code откройте файл dataconnect/connector/queries.gql
и добавьте запрос ListMovies
:
query ListMovies @auth(level: PUBLIC) {
movies {
id
title
imageUrl
releaseYear
genre
rating
tags
description
}
}
Чтобы протестировать новый запрос, нажмите кнопку «Выполнить (локально)» , чтобы выполнить запрос к вашей локальной базе данных. Список фильмов из базы данных должен отображаться в разделе «Результаты» терминала Data Connect Execution.
Подключите запрос ListMovies к главному экрану приложения.
Теперь, когда вы протестировали запрос в эмуляторе подключения к данным, вы можете вызвать его из своего приложения.
Когда вы сохраняете queries.gql
, Firebase Data Connect генерирует код, соответствующий запросу ListMovies
в пакете FriendlyFlixSDK
.
В Xcode откройте Movie+DataConnect.swift
и добавьте следующий код для сопоставления ListMoviesQuery.Data.Movie
с 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
}
}
Откройте файл HomeScreen.swift
и обновите его, используя следующий фрагмент кода.
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) ?? []
}
...
}
Запрос |
Запустите приложение
В Xcode нажмите кнопку «Выполнить» , чтобы запустить приложение в симуляторе iOS.
После запуска приложения вы должны увидеть экран, который выглядит следующим образом:
Вы могли заметить, что во всех областях приложения (главный раздел, лучшие фильмы и список просмотра) отображается один и тот же список. Это связано с тем, что вы используете один и тот же запрос для всех этих представлений. В следующих разделах вы будете реализовывать пользовательские запросы. |
6. Отображение героев и лучших фильмов
На этом этапе вы сосредоточитесь на обновлении способа отображения фильмов в главном разделе (это заметная карусель в верхней части главного экрана), а также в разделе самых популярных фильмов ниже.
В настоящее время запрос ListMovies извлекает все фильмы. Чтобы оптимизировать отображение этих разделов, вы ограничите количество фильмов, возвращаемых каждым запросом. Текущая реализация запроса ListMovies
еще не предлагает встроенной поддержки ограничения результатов — добавление поддержки ограничения и упорядочивания — это то, что вы добавите в этом разделе.
Улучшение запроса ListMovies
Откройте queries.gql
и обновите ListMovies
следующим образом, чтобы добавить поддержку упорядочивания и ограничения:
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
}
}
Это позволит вам ограничить количество фильмов, возвращаемых запросом, и упорядочить набор результатов по рейтингу и году выпуска.
Как только вы сохраните этот файл, Firebase Data Connect автоматически повторно сгенерирует код в FriendlyFlixSDK
. На следующем шаге вы можете обновить код HomeScreen.swift
, чтобы использовать эти дополнительные функции.
Используйте расширенный запрос в пользовательском интерфейсе
Вернитесь в Xcode, чтобы внести необходимые изменения в HomeScreen.swift
.
Сначала обновите heroMoviesRef
, чтобы получить 3 последних выпущенных фильма:
struct HomeScreen {
...
init() {
heroMoviesRef = connector.listMoviesQuery
.ref { optionalVars in
optionalVars.limit = 3
optionalVars.orderByReleaseYear = .DESC
}
}
}
Затем настройте еще одну ссылку на запрос для лучших фильмов и установите фильтр на 5 фильмов с самым высоким рейтингом:
struct HomeScreen {
...
let topMoviesRef: QueryRefObservation<ListMoviesQuery.Data, ListMoviesQuery.Variables>
init() {
heroMoviesRef = ...
topMoviesRef = connector.listMoviesQuery
.ref { optionalVars in
optionalVars.limit = 5
optionalVars.orderByRating = .DESC
}
}
}
Наконец, обновите вычисляемое свойство, которое связывает результат этого запроса с пользовательским интерфейсом:
extension HomeScreen {
...
private var topMovies: [Movie] {
topMoviesRef.data?.movies.map(Movie.init) ?? []
}
}
Посмотрите это в действии
Запустите приложение еще раз, чтобы увидеть 3 последних фильма в разделе «Герои» и 5 фильмов с самым высоким рейтингом в разделе «Лучшие фильмы»:
7. Отображение информации о фильме и актере
Теперь пользователь может просматривать фильмы. При нажатии на карточку фильма им будут показаны некоторые подробности о фильме, но вы могли заметить, что в деталях отсутствует определенное количество, ну... деталей!
Это связано с тем, что мы получили только столько информации о каждом фильме, сколько нам нужно для отображения раздела героя фильма и раздела лучших фильмов: название фильма, краткое описание и URL-адрес изображения.
На странице сведений о фильме мы хотим показать дополнительную информацию о фильме. В этом разделе вы улучшите приложение, чтобы оно могло отображать актеров фильма и любые обзоры на странице сведений.
Для этого вам нужно будет сделать пару вещей:
- Улучшите схему для поддержки киноактеров и обзоров.
- Напишите запросы Firebase Data Connect для получения подробной информации о данном фильме.
- Отображение результатов на экране сведений о фильме
Улучшите схему
В VS Code откройте dataconnect/schema/schema.gql
и добавьте определения схемы для Actor
и 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"
}
Добавьте фиктивные данные для актеров
После обновления схемы вы можете заполнить базу данных дополнительными фиктивными данными для тестирования.
- В Finder скопируйте
finish/FriendlyFlix/dataconnect/moviededetails_insert.gql
в папкуstart/FriendlyFlix/dataconnect
. - В VS Code откройте
dataconnect/moviededetails_insert.gql
. - Убедитесь, что эмуляторы в расширении Firebase Data Connect работают.
- В верхней части файла вы должны увидеть кнопку «Выполнить» (локальную) . Нажмите эту кнопку, чтобы вставить данные макета фильма в вашу базу данных.
- Проверьте терминал Data Connect Execution, чтобы убедиться, что данные были успешно добавлены.
Имея данные, перейдите к следующему шагу, чтобы определить запрос для получения сведений о фильме.
Определите запрос GetMovieById
В VS Code откройте файл dataconnect/connector/queries.gql
и добавьте запрос 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
}
}
}
Подключите запрос GetMovieById к MovieDetailsView.
В Xcode откройте файл MovieDetailsView.swift
и обновите вычисляемое свойство movieDetails
, чтобы оно соответствовало следующему коду:
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
}
}
Запустите приложение
В Xcode нажмите кнопку «Выполнить» , чтобы запустить приложение в симуляторе iOS.
После запуска приложения коснитесь карточки фильма, чтобы отобразить подробную информацию о фильме. Это должно выглядеть так:
8. Внедрить аутентификацию пользователей
В настоящее время приложение предоставляет неперсонализированную информацию о фильмах и актерах. На следующих шагах вы реализуете функции, которые связывают данные с вошедшим в систему пользователем. Вы начнете с того, что разрешите пользователям добавлять фильмы в свой личный список просмотра.
Прежде чем вы сможете реализовать функцию списка наблюдения, вам сначала необходимо установить личность пользователя. Чтобы сделать это возможным, вы интегрируете проверку подлинности Firebase, позволяя пользователям входить в приложение.
Возможно, вы уже заметили кнопку аватара пользователя в правом верхнем углу главного экрана. Нажав на нее, вы попадете на экран, на котором пользователи смогут зарегистрироваться или войти в систему, используя свой адрес электронной почты и пароль.
Как только пользователь успешно войдет в систему, вашему приложению потребуется сохранить его основные данные, в первую очередь уникальный идентификатор пользователя и выбранное имя пользователя.
Включить аутентификацию Firebase
В консоли Firebase вашего проекта перейдите в раздел «Аутентификация» и включите аутентификацию Firebase. Затем включите поставщика аутентификации по электронной почте и паролю.
В локальной папке проекта найдите firebase.json
и обновите его следующим образом, чтобы включить эмулятор аутентификации Firebase.
{
"emulators": {
"dataconnect": {
},
"auth": {
}
},
"dataconnect": {
"source": "dataconnect"
}
}
После этого вам необходимо остановить и перезапустить эмулятор Firebase, чтобы изменения вступили в силу.
Реализация обработчика аутентификации
В следующем разделе вы реализуете логику, связывающую аутентификацию пользователя с вашей базой данных. Это предполагает создание обработчика аутентификации, который прослушивает успешные входы в систему.
После аутентификации пользователя этот обработчик автоматически инициирует создание соответствующей учетной записи в вашей базе данных.
В Xcode откройте файл AuthenticationService.swift
и добавьте следующий код:
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
}
}
Это универсальный обработчик аутентификации, который позволяет использовать onSignUp
для регистрации замыкания, которое будет вызываться, когда пользователь войдет в систему.
Внутри этого замыкания вы можете создать новую учетную запись пользователя в базе данных. Но прежде чем вы сможете это сделать, вам необходимо создать мутацию, которая позволит вам создавать или обновлять новых пользователей в базе данных.
Добавьте сущность «Пользователь» в схему
Тип User
определяет сущность пользователя. Пользователи могут взаимодействовать с фильмами, оставляя отзывы или добавляя фильмы в избранное.
В VS Code откройте файл dataconnect/schema/schema.gql
и добавьте следующее определение таблицы 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)")
}
Определите мутацию для вставки или обновления пользователя
В VS Code откройте файл dataconnect/connector/mutations.gql
и добавьте мутацию UpsertUser
:
mutation UpsertUser($username: String!) @auth(level: USER) {
user_upsert(
data: {
id_expr: "auth.uid"
username: $username
}
)
}
Создайте нового пользователя после успешного входа в систему
В Xcode откройте FriendlyFlixApp.swift
и добавьте в инициализатор следующий код:
@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 {
...
}
}
Этот код использует upsertUserMutation
Firebase Data Connect, созданный для вставки нового пользователя (или обновления существующего пользователя с тем же идентификатором) каждый раз, когда пользователь успешно регистрируется с использованием аутентификации Firebase.
Посмотрите это в действии
Чтобы убедиться, что это работает, сначала зарегистрируйтесь в приложении iOS:
- Если вы этого не сделали, остановите и перезапустите эмулятор Firebase, чтобы убедиться, что эмулятор аутентификации Firebase работает.
- В Xcode нажмите кнопку «Выполнить» , чтобы запустить приложение в симуляторе iOS.
- Нажмите на значок аватара в правом верхнем углу экрана.
- Перейдите к процессу регистрации и зарегистрируйтесь в приложении.
Затем запросите базу данных, чтобы убедиться, что приложение создало новую учетную запись для пользователя:
- В VS Code откройте
dataconnect/schema/schema.gql
и нажмите «Прочитать данные» в сущности «User
. - Это создаст новый файл запроса с именем
User_read.gql
- Нажмите « Запустить локально», чтобы увидеть всех пользователей в таблице пользователей.
- На панели «Выполнение подключения к данным» теперь вы должны увидеть учетную запись пользователя, с которым вы только что зарегистрировались.
9. Управление любимыми фильмами
В этом разделе лаборатории кода вы реализуете взаимодействие с пользователем в приложении для просмотра фильмов, в частности позволяя пользователям управлять своими любимыми фильмами. Фильмы, отмеченные как избранные, появятся в разделе списка просмотра приложения.
Улучшите схему для поддержки избранного
Тип FavoriteMovie
— это таблица соединений, которая обрабатывает отношения «многие ко многим» между пользователями и их любимыми фильмами. Каждая таблица связывает User
с Movie
.
Скопируйте и вставьте фрагмент кода в файл 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!
}
Определите мутации для добавления и удаления избранного
Прежде чем приложение сможет отображать любимые фильмы пользователя, пользователю необходимо указать, какие из них являются его любимыми. Для этого сначала нужно добавить две мутации, чтобы пометить фильм как один из избранных пользователя, или снова удалить его из избранного соответственно.
- В VS Code
mutations.gql
вdataconnect/connector/mutations.gql
- Добавьте следующие мутации для обработки избранных фильмов:
## 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 })
}
Подключите мутации к пользовательскому интерфейсу вашего приложения.
Пользователи могут пометить фильм как избранный, щелкнув значок сердечка на экране сведений о фильме.
Чтобы связать только что созданные мутации с пользовательским интерфейсом приложения, внесите следующие изменения в MovieCardView
:
- Импортируйте
FriendlyFlixSDK
и настройте соединитель.
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
...
}
- Реализуйте метод
toggleFavourite
. Он будет вызываться всякий раз, когда пользователь нажимает на значок сердца в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)
}
}
}
}
Это обновит состояние избранного текущего фильма в базе данных. Последний шаг, которого не хватает, — убедиться, что состояние пользовательского интерфейса отображается соответствующим образом.
Определите запрос, чтобы выяснить, помечен ли фильм как избранный.
- В VS Code откройте
queries.gql
вdataconnect/connector
. - Добавьте следующий запрос, чтобы проверить, помечен ли фильм как избранный:
query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) {
favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) {
movieId
}
}
- В Xcode создайте экземпляр ссылки на запрос
GetIfFavoritedMovie
и реализуйте вычисляемое свойство, которое определяет, помечен ли фильм, показанный в этомMovieCardView
, как избранный для текущего пользователя.
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
}
...
}
- Обновите код в
toggleFavourite
, чтобы запрос выполнялся всякий раз, когда пользователь нажимает кнопку. Это гарантирует, что вычисляемое свойствоisFavourite
всегда возвращает правильное значение.
private func toggleFavourite() {
Task {
if isFavourite {
...
}
let _ = try await isFavouriteRef.execute()
}
}
Получите любимые фильмы
В качестве последнего шага для этой функции вы реализуете получение любимых фильмов пользователей, чтобы они могли видеть их в своем списке просмотра.
- В VS Code откройте
queries.gql
вdataconnect/connector/queries.gql
и вставьте следующий запрос:
## 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
}
}
}
}
Список любимых фильмов пользователя отображается на LibraryScreen
. На этом экране должны отображаться данные только в том случае, если пользователь вошел в систему, поэтому сначала подключите состояние аутентификации экрана к AuthenticationService
приложения.
- Добавьте код для сопоставления
FavoriteMovieFavoriteMovies
сMovie
в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
}
}
- В Xcode откройте
LibraryScreen
, затем обновитеisSignedIn
следующим образом:
struct LibraryScreen: View {
...
private var isSignedIn: Bool {
authenticationService.user != nil
}
}
- Затем импортируйте Firebase Data Connect и FriendlyFlixSDK и получите ссылку на запрос
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) ?? []
}
...
}
- Убедитесь, что запрос
watchListRef
выполняется при появлении представления:
extension LibraryScreen: View {
var body: some View {
...
MovieListSection(namespace: namespace, title: "Watch List", movies: watchList)
.onAppear {
Task {
try await watchListRef.execute()
}
...
Посмотрите это в действии
Теперь вы можете запустить приложение и опробовать только что реализованную функцию избранного. Несколько вещей, которые следует иметь в виду:
- Убедитесь, что эмулятор Firebase запущен.
- Убедитесь, что вы добавили фиктивные данные для фильмов и сведения о них.
- Убедитесь, что вы зарегистрировались как пользователь
- В Xcode нажмите кнопку «Выполнить» , чтобы запустить приложение в симуляторе iOS.
- После запуска приложения коснитесь карточки фильма, чтобы отобразить подробную информацию о фильме.
- Нажмите на значок сердечка, чтобы отметить фильм как избранный. Сердце должно стать твердым.
- Повторите это для пары фильмов.
- Перейдите на вкладку «Библиотека». Теперь вы должны увидеть список всех фильмов, которые вы отметили как избранные.
10. Поздравления
Поздравляем, вы успешно добавили Firebase Data Connect в приложение iOS! Теперь вы знаете ключевые шаги, необходимые для настройки подключения к данным, создания запросов и изменений, а также выполнения аутентификации пользователей.
Необязательно: развертывание в рабочей среде
До сих пор это приложение использовало только эмуляторы Firebase. Если вы хотите узнать, как развернуть это приложение в реальном проекте Firebase, перейдите к следующему шагу.
11. (Необязательно) Разверните свое приложение.
До сих пор это приложение было полностью локальным, все данные содержатся в пакете эмулятора Firebase. В этом разделе вы узнаете, как настроить проект Firebase, чтобы это приложение работало в рабочей среде.
Включить аутентификацию Firebase
- В консоли Firebase перейдите в раздел «Аутентификация» и нажмите «Начать» .
- Перейдите на вкладку «Метод входа» .
- Выберите опцию «Электронная почта/пароль» в разделе «родные провайдеры»,
- Включите поставщика электронной почты и пароля, затем нажмите « Сохранить» .
Включить подключение к данным Firebase
Важно! Если вы впервые развертываете схему в проекте, в результате этого процесса будет создан экземпляр Cloud SQL PostgreSQL, что может занять около 15 минут. Вы не сможете выполнить развертывание, пока экземпляр Cloud SQL не будет готов и не интегрирован с Firebase Data Connect.
1. В пользовательском интерфейсе расширения Firebase Data Connect VS Code нажмите «Развернуть в производство» . 2. Возможно, вам придется просмотреть изменения схемы и одобрить потенциально разрушительные изменения. Вам будет предложено: - просмотреть изменения схемы с помощью firebase dataconnect:sql:diff
- если вы удовлетворены изменениями, примените их, используя поток, запущенный firebase dataconnect:sql:migrate
Ваш экземпляр Cloud SQL для PostgreSQL будет обновлен с учетом окончательной развернутой схемы и данных. Вы можете отслеживать статус в консоли Firebase.
Теперь вы можете нажать «Выполнить (производство)» на панели подключения к данным Firebase, как и в случае с локальными эмуляторами, чтобы добавить данные в производственную среду.
Прежде чем снова запустить приложение iOS, убедитесь, что оно подключается к рабочему экземпляру вашего проекта:
- Откройте меню Продукт > Схема > Изменить схему....
- В разделе «Выполнить» снимите флажок с аргумента запуска
-useEmulator YES
.