1. סקירה כללית
בקודלאב הזה תלמדו איך לשלב את Firebase Data Connect עם מסד נתונים של Cloud SQL כדי ליצור אפליקציה של ביקורות סרטים ל-iOS באמצעות SwiftUI.
נלמד איך לחבר את אפליקציית iOS למסד נתונים של Cloud SQL באמצעות Firebase Data Connect, כדי לאפשר סנכרון נתונים חלק של ביקורות על סרטים.
בסיום הקודלאב הזה תהיה לכם אפליקציית iOS פונקציונלית שמאפשרת למשתמשים לעיין בסרטים ולסמן סרטים בתור מועדפים. כל זה מתבסס על מסד נתונים של Cloud SQL באמצעות Firebase Data Connect.
מה תלמדו
ב-codelab הזה תלמדו איך:
- הגדרה של Firebase Data Connect באמצעות חבילת Firebase Emulator, כדי לקצר את זמני הטיפול.
- עיצוב סכימה של מסד נתונים באמצעות Data Connect ו-GraphQL.
- יצירת SDK של Swift ללא שגיאות טיפוס מתבנית מסד הנתונים והוספתו לאפליקציית Swift.
- מטמיעים אימות משתמשים ומשלבים אותו עם Firebase Data Connect כדי לאבטח את נתוני המשתמשים.
- אחזור, עדכון, מחיקה וניהול של נתונים ב-Cloud SQL באמצעות שאילתות ומוטציות שמבוססות על GraphQL.
- (אופציונלי) פורסים שירות Data Connect בסביבת הייצור.
דרישות מוקדמות
- הגרסה האחרונה של Xcode
- הקוד לדוגמה ב-Codelab. תורידו את הקוד לדוגמה באחד מהשלבים הראשונים של codelab.
2. הגדרת פרויקט לדוגמה
יצירת פרויקט Firebase
- נכנסים למסוף Firebase באמצעות חשבון Google.
- במסוף Firebase, לוחצים על Create a Firebase project (יצירת פרויקט Firebase).
- מזינים שם לפרויקט ב-Firebase (לדוגמה, 'Friendly Flix') ולוחצים על המשך.
- יכול להיות שתתבקשו להפעיל את התכונה 'עזרה מ-AI' לפרויקט Firebase. לצורך הקודלאב הזה, הבחירה שלכם לא משנה.
- יכול להיות שתתבקשו להפעיל את Google Analytics. לצורכי הקודלאב הזה, הבחירה שלכם לא משנה.
- אחרי דקה בערך, פרויקט Firebase יהיה מוכן. לוחצים על המשך.
מורידים את הקוד
מריצים את הפקודה הבאה כדי לשכפל את קוד הדוגמה של סדנת הקוד הזו. הפקודה הזו תיצור ספרייה בשם codelab-dataconnect-ios
במחשב:
git clone https://github.com/peterfriese/codelab-dataconnect-ios`
אם אין לכם את git במחשב, אתם יכולים גם להוריד את הקוד ישירות מ-GitHub.
הוספת הגדרות של Firebase
Firebase SDK משתמש בקובץ תצורה כדי להתחבר לפרויקט Firebase. בפלטפורמות של Apple, הקובץ הזה נקרא GoogleServices-Info.plist
. בשלב הזה, מורידים את קובץ התצורה ומוסיפים אותו לפרויקט ב-Xcode.
- במסוף Firebase, בוחרים באפשרות סקירה כללית של הפרויקט בתפריט הניווט הימני.
- לוחצים על הלחצן iOS+ כדי לבחור את הפלטפורמה. כשמוצגת בקשה להזין את מזהה החבילה של Apple, מזינים
com.google.firebase.samples.FriendlyFlix
. - לוחצים על Register app ופועלים לפי ההוראות להורדת הקובץ
GoogleServices-Info.plist
. - מעבירים את הקובץ שהורדתם לספרייה
start/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/
של הקוד שהורדתם, מחליפים את קובץGoogleServices-Info.plist
הקיים. - לאחר מכן לוחצים על הבא כמה פעמים כדי להשלים את פרויקט ההגדרה במסוף Firebase (אין צורך להוסיף את ה-SDK לאפליקציה, כי זה כבר בוצע בשבילכם בפרויקט ההתחלתי).
- לסיום, לוחצים על Continue to console כדי לסיים את תהליך ההגדרה.
3. הגדרת Data Connect
התקנה
התקנה אוטומטית
מריצים את הפקודה הבאה בספרייה codelab-dataconnect-ios/FriendlyFlix
:
curl -sL https://firebase.tools/dataconnect | bash
הסקריפט הזה מנסה להגדיר את סביבת הפיתוח ולהפעיל סביבת פיתוח משולבת (IDE) מבוססת-דפדפן. סביבת הפיתוח המשולבת הזו מספקת כלים, כולל תוסף מובנה מראש ל-VS Code, שיעזרו לכם לנהל את הסכימה ולהגדיר שאילתות ומוטציות לשימוש באפליקציה, וגם ליצור ערכות SDK עם סוגים מוגדרים.
אחרי הרצת הסקריפט, VS Code אמור להיפתח באופן אוטומטי.
אחרי שמבצעים את הפעולה הזו פעם אחת, אפשר להפעיל את VS Code על ידי הפעלת VS Code בספרייה המקומית:
code .
התקנה ידנית
- התקנת Visual Studio Code
- התקנה של Node.js
- ב-VS Code, פותחים את הספרייה
codelab-dataconnect-ios/FriendlyFlix
. - מתקינים את התוסף Firebase Data Connect מ-Visual Studio Code Marketplace.
איך מפעילים את Data Connect בפרויקט
בחלונית הימנית, לוחצים על סמל Firebase כדי לפתוח את ממשק המשתמש של התוסף Data Connect ל-VS Code.
- לוחצים על הלחצן כניסה באמצעות חשבון Google. ייפתח חלון דפדפן. פועלים לפי ההוראות כדי להיכנס לתוסף באמצעות חשבון Google.
- לוחצים על הלחצן Connect a Firebase project (קישור פרויקט Firebase) ובוחרים את הפרויקט שיצרתם קודם במסוף.
- לוחצים על הלחצן Run firebase init ופועלים לפי השלבים במסוף המובנה.
הגדרת יצירת SDK
אחרי שלוחצים על הלחצן Run firebase init, התוסף 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 ולוחצים על הלחצן Start emulators.
הפעולה הזו תפעיל את Firebase Emulator בטרמינל המשולב. הפלט אמור להיראות כך:
npx -y firebase-tools@latest emulators:start --project <your-project-id>
הוספת החבילה שנוצרה לאפליקציית Swift
- פתיחת
FriendlyFlix/app/FriendlyFlix/FriendlyFlix.xcodeproj
ב-Xcode - בוחרים באפשרות File > Add Package Dependencies… (קובץ > הוספת יחסי תלות בין חבילות…).
- לוחצים על Add Local… (הוספת קובץ מקומי…) ואז מוסיפים את החבילה
FriendlyFlixSDK
מהתיקייהFriendlyFlix/app
. - מחכים ש-Xcode יפתור את יחסי התלות בחבילות.
- בתיבת הדו-שיח Choose Package Products for FriendlyFlixSDK, בוחרים ב-
FriendlyFlix
כיעד ולוחצים על Add Package.
הגדרת אפליקציית iOS לשימוש במהדורת האפליקציה במחשב
- פתיחת
FriendlyFlixApp.swift
. (אפשר להקיש על CMD + Shift + O כדי לפתוח את תיבת הדו-שיח פתיחה מהירה, ואז להקליד FriendlyFlixApp כדי למצוא את הקובץ במהירות) - מייבאים את Firebase, Firebase Auth, Firebase Data Connect ואת ה-SDK שנוצר עבור הסכימה
- מגדירים את Firebase ב-initializer.
- מוודאים ש-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 בתפריט הנפתח Destination.
- מקישים על CMD+R (או לוחצים על הלחצן Run) ב-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
הסוג 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
}
}
כדי לבדוק את השאילתה החדשה, לוחצים על הלחצן הפעלה (מקומית) כדי להריץ את השאילתה במסד הנתונים המקומי. רשימת הסרטים ממסד הנתונים אמורה להופיע בקטע Results (תוצאות) במסוף Data Connect Execution.
חיבור השאילתה ListMovies למסך הבית של האפליקציה
עכשיו, אחרי שבדקתם את השאילתה במהדמנת Data Connect, אתם יכולים להפעיל את השאילתה מתוך האפליקציה.
כששומרים את 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, לוחצים על הלחצן Run כדי להפעיל את האפליקציה בסימולטור 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
. - פותחים את
dataconnect/moviededetails_insert.gql
ב-VS Code. - מוודאים שהמעבדים הווירטואליים בתוסף Firebase Data Connect פועלים.
- בחלק העליון של הקובץ אמור להופיע הלחצן הפעלה (מקומית). לוחצים עליו כדי להוסיף את נתוני הסרט המדומה למסד הנתונים.
- בודקים את מסוף הביצוע של Data Connect כדי לוודא שהנתונים נוספו בהצלחה.
אחרי שמוסיפים את הנתונים, עוברים לשלב הבא כדי להגדיר את השאילתה לאחזור פרטי הסרט.
הגדרת השאילתה 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, לוחצים על הלחצן Run כדי להפעיל את האפליקציה בסימולטור iOS.
אחרי שהאפליקציה מופעלת, מקישים על כרטיס של סרט כדי להציג את פרטי הסרט. הוא אמור להיראות כך:
8. הטמעת אימות משתמשים
בשלב זה, האפליקציה מציגה מידע על סרטים ושחקנים ללא התאמה אישית. בשלבים הבאים תבצעו הטמעה של תכונות שמשויכות לנתונים של המשתמש שמחובר לחשבון. בשלב הראשון, תצטרכו לאפשר למשתמשים להוסיף סרטים לרשימת הצפייה האישית שלהם.
לפני שאפשר להטמיע את התכונה 'רשימת מעקב', צריך קודם להגדיר את זהות המשתמש. כדי לעשות זאת, משלבים את האימות ב-Firebase ומאפשרים למשתמשים להיכנס לאפליקציה.
יכול להיות שכבר שמתם לב ללחצן הדמות של המשתמש בפינה השמאלית העליונה של מסך הבית. הקשה עליו תוביל למסך שבו המשתמשים יכולים להירשם או להיכנס באמצעות כתובת האימייל והסיסמה שלהם.
אחרי שמשתמש נכנס לחשבון, האפליקציה צריכה לאחסן את הפרטים החיוניים שלו, בעיקר את מזהה המשתמש הייחודי ואת שם המשתמש שבחר.
הפעלת אימות ב-Firebase
במסוף Firebase של הפרויקט, עוברים לקטע Authentication (אימות) ומפעילים את Firebase Authentication. לאחר מכן, מפעילים את ספק האימות באמצעות אימייל/סיסמה.
בתיקיית הפרויקט המקומית, מחפשים את הקובץ 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, לוחצים על הלחצן Run כדי להפעיל את האפליקציה בסימולטור iOS.
- לוחצים על סמל הדמות בפינה השמאלית העליונה של המסך.
- עוברים לתהליך הרשמה ונרשמים לאפליקציה.
לאחר מכן, שולחים שאילתה למסד הנתונים כדי לוודא שהאפליקציה יצרה חשבון משתמש חדש למשתמש:
- ב-VS Code, פותחים את
dataconnect/schema/schema.gql
ולוחצים על Read data (קריאת נתונים) בישותUser
. - הפעולה הזו תיצור קובץ שאילתה חדש בשם
User_read.gql
- לוחצים על Run local כדי לראות את כל המשתמשים בטבלת המשתמשים.
- בחלונית Data Connect Execution אמור להופיע עכשיו חשבון של המשתמש שאליו נרשמת זה עתה
9. ניהול הסרטים המועדפים
בקטע הזה של Codelab, נתכנת אינטראקציות של משתמשים באפליקציה של ביקורות הסרטים, וניתן למשתמשים אפשרות לנהל את הסרטים המועדפים עליהם. סרטים שמסומנים כמועדפים יופיעו בקטע 'רשימת הצפייה' באפליקציה.
שיפור הסכימה לתמיכה במועדפים
הטיפוס 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 Emulator פועל
- מוודאים שהוספתם נתונים מדומים של סרטים ופרטי סרטים
- מוודאים שנרשמתם כמשתמשים
- ב-Xcode, לוחצים על הלחצן Run כדי להפעיל את האפליקציה בסימולטור iOS.
- אחרי שהאפליקציה מופעלת, מקישים על כרטיס של סרט כדי להציג את פרטי הסרט.
- מקישים על סמל הלב כדי לסמן את הסרט כמועדף. הלב אמור להפוך למוצק.
- חוזרים על הפעולה הזו עם כמה סרטים.
- עוברים לכרטיסייה 'ספרייה'. עכשיו אמורה להופיע רשימה של כל הסרטים שסימנתם כ'מועדפים'.
10. מזל טוב
מזל טוב, הוספת את Firebase Data Connect לאפליקציה ל-iOS! עכשיו אתם יודעים מהם השלבים העיקריים להגדרת Data Connect, ליצירת שאילתות ומוטציות ולטיפול באימות משתמשים.
אופציונלי: פריסה בסביבת הייצור
עד כה, האפליקציה הזו השתמשה רק במהדמנים של Firebase. כדי ללמוד איך לפרוס את האפליקציה הזו בפרויקט Firebase אמיתי, ממשיכים לשלב הבא.
11. (אופציונלי) פריסת האפליקציה
עד כה האפליקציה הזו הייתה מקומית לחלוטין, וכל הנתונים נכללים ב-Firebase Emulator Suite. בקטע הזה תלמדו איך להגדיר את פרויקט Firebase כך שהאפליקציה הזו תפעל בסביבת הייצור.
הפעלת אימות ב-Firebase
- במסוף Firebase, עוברים לקטע Authentication ולוחצים על Get started.
- עוברים לכרטיסייה Sign-in method (שיטת כניסה).
- בוחרים באפשרות 'אימייל/סיסמה' בקטע 'ספקים מקומיים',
- מפעילים את הספק של האימייל/הסיסמה ולוחצים על Save.
הפעלת Firebase Data Connect
חשוב: אם זו הפעם הראשונה שאתם פורסים סכימה בפרויקט, התהליך הזה ייצור מכונה של PostgreSQL ב-Cloud SQL. התהליך עשוי להימשך כ-15 דקות. לא תוכלו לפרוס את הקוד עד שהמכונה של Cloud SQL תהיה מוכנה ותשולב עם Firebase Data Connect.
1. בממשק המשתמש של התוסף של Firebase Data Connect ל-VS Code, לוחצים על פריסה בסביבת הייצור. 2. יכול להיות שתצטרכו לבדוק שינויים בסכימה ולאשר שינויים שעלולים להיות הרסניים. תוצג לכם בקשה: - לבדוק את השינויים בסכימה באמצעות firebase dataconnect:sql:diff
- כשתהיו מרוצים מהשינויים, תוכלו להחיל אותם באמצעות התהליך שמתחיל ב-firebase dataconnect:sql:migrate
המכונה של Cloud SQL for PostgreSQL תתעדכן עם הסכימה והנתונים הסופיים שנפרסו. אפשר לעקוב אחרי הסטטוס במסוף Firebase.
עכשיו אפשר ללחוץ על 'הפעלה (ייצור)' בחלונית של Firebase Data Connect, בדיוק כמו שעשיתם עם המהדמנים המקומיים, כדי להוסיף נתונים לסביבת הייצור.
לפני שמפעילים שוב את אפליקציית iOS, צריך לוודא שהיא מתחברת למכונה של הפרויקט בסביבת הייצור:
- פותחים את התפריט Product (מוצר) > Scheme (סכימה) > Edit Scheme… (עריכת הסכימה…).
- בקטע Run, מבטלים את הסימון של ארגומנט ההפעלה
-useEmulator YES
.