ساخت با Firebase Data Connect (iOS / Swift)

۱. مرور کلی

این آزمایشگاه کد شما را در فرآیند ادغام Firebase Data Connect با یک پایگاه داده Cloud SQL برای ساخت یک برنامه نقد فیلم برای iOS با استفاده از SwiftUI راهنمایی می‌کند.

شما یاد خواهید گرفت که چگونه برنامه iOS خود را با استفاده از Firebase Data Connect به یک پایگاه داده Cloud SQL متصل کنید و همگام‌سازی یکپارچه داده‌ها را برای بررسی فیلم‌ها امکان‌پذیر کنید.

در پایان این آزمایشگاه کد، شما یک برنامه iOS کاربردی خواهید داشت که به کاربران امکان می‌دهد فیلم‌ها را مرور کنند و فیلم‌ها را به عنوان موارد دلخواه علامت‌گذاری کنند، همه اینها توسط یک پایگاه داده Cloud SQL با استفاده از قدرت Firebase Data Connect پشتیبانی می‌شود.

آنچه یاد خواهید گرفت

این آزمایشگاه کد به شما یاد می‌دهد که چگونه:

  • برای سرعت بخشیدن به فرآیند، با استفاده از مجموعه شبیه‌ساز Firebase، Firebase Data Connect را راه‌اندازی کنید .
  • طراحی یک طرح پایگاه داده با استفاده از Data Connect و GraphQL
  • یک کیت توسعه نرم‌افزار سویفت از نوع typesafe از طرح پایگاه داده خود ایجاد کنید و آن را به یک برنامه سویفت اضافه کنید.
  • احراز هویت کاربر را پیاده‌سازی کنید و آن را با Firebase Data Connect ادغام کنید تا داده‌های کاربران خود را ایمن کنید.
  • بازیابی، به‌روزرسانی، حذف و مدیریت داده‌ها در Cloud SQL با استفاده از کوئری‌ها و جهش‌های ارائه شده توسط GraphQL.
  • (اختیاری) یک سرویس Data Connect را در محیط عملیاتی مستقر کنید .

پیش‌نیازها

  • آخرین نسخه Xcode
  • کد نمونه codelab. شما کد نمونه را در یکی از اولین مراحل codelab دانلود خواهید کرد.

۲. پروژه نمونه را تنظیم کنید

ایجاد یک پروژه فایربیس

  1. با استفاده از حساب گوگل خود وارد کنسول فایربیس شوید.
  2. برای ایجاد یک پروژه جدید، روی دکمه کلیک کنید و سپس نام پروژه را وارد کنید (برای مثال، Friendly Flix ).
  3. روی ادامه کلیک کنید.
  4. در صورت درخواست، شرایط Firebase را مرور و قبول کنید و سپس روی ادامه کلیک کنید.
  5. (اختیاری) دستیار هوش مصنوعی را در کنسول Firebase (با نام "Gemini در Firebase") فعال کنید.
  6. برای این codelab، به گوگل آنالیتیکس نیاز ندارید ، بنابراین گزینه گوگل آنالیتیکس را غیرفعال کنید .
  7. روی ایجاد پروژه کلیک کنید، منتظر بمانید تا پروژه شما آماده شود و سپس روی ادامه کلیک کنید.

کد را دانلود کنید

دستور زیر را برای کپی کردن کد نمونه برای این codelab اجرا کنید. این دستور یک دایرکتوری به نام codelab-dataconnect-ios در دستگاه شما ایجاد می‌کند:

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

اگر گیت را روی دستگاه خود ندارید، می‌توانید کد را مستقیماً از گیت‌هاب دانلود کنید.

پیکربندی Firebase را اضافه کنید

کیت توسعه نرم‌افزار فایربیس (Firebase SDK) از یک فایل پیکربندی برای اتصال به پروژه فایربیس شما استفاده می‌کند. در پلتفرم‌های اپل، این فایل GoogleServices-Info.plist نام دارد. در این مرحله، فایل پیکربندی را دانلود کرده و به پروژه Xcode خود اضافه خواهید کرد.

  1. در کنسول Firebase ، در منوی سمت چپ، گزینه Project Overview را انتخاب کنید.
  2. برای انتخاب پلتفرم، روی دکمه iOS+ کلیک کنید. وقتی از شما شناسه بسته اپل (Apple bundle ID ) خواسته شد، com.google.firebase.samples.FriendlyFlix استفاده کنید.
  3. روی ثبت برنامه کلیک کنید و دستورالعمل‌ها را برای دانلود فایل GoogleServices-Info.plist دنبال کنید.
  4. فایل دانلود شده را به دایرکتوری start/FriendlyFlix/app/FriendlyFlix/FriendlyFlix/ که کدی که دانلود کرده‌اید در آن قرار دارد، منتقل کنید و آن را جایگزین فایل GoogleServices-Info.plist موجود کنید.
  5. سپس چند بار روی Next کلیک کنید تا پروژه راه‌اندازی در کنسول Firebase تکمیل شود (نیازی به اضافه کردن SDK به برنامه نیست، زیرا این کار قبلاً در پروژه اولیه برای شما انجام شده است).
  6. در نهایت، برای اتمام مراحل راه‌اندازی، روی «ادامه به کنسول» کلیک کنید.

۳. اتصال داده را راه‌اندازی کنید

نصب

نصب خودکار

دستور زیر را در دایرکتوری codelab-dataconnect-ios/FriendlyFlix اجرا کنید:

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

این اسکریپت سعی می‌کند محیط توسعه را برای شما راه‌اندازی کند و یک IDE مبتنی بر مرورگر را راه‌اندازی کند. این IDE ابزارهایی از جمله یک افزونه VS Code از پیش بسته‌بندی شده را ارائه می‌دهد تا به شما در مدیریت طرحواره خود و تعریف پرس‌وجوها و جهش‌هایی که باید در برنامه خود استفاده کنید و SDK های با نوع قوی تولید کند، کمک کند.

پس از اجرای اسکریپت، VS Code باید به طور خودکار باز شود.

بعد از اینکه این کار را یک بار انجام دادید، می‌توانید VS Code را با اجرای VS Code در دایرکتوری محلی اجرا کنید:

code .

نصب دستی

  1. نصب ویژوال استودیو کد
  2. نصب Node.js
  3. در VS Code، دایرکتوری codelab-dataconnect-ios/FriendlyFlix را باز کنید.
  4. افزونه‌ی Firebase Data Connect را از Visual Studio Code Marketplace نصب کنید.

مقداردهی اولیه Data Connect در پروژه

در پنل سمت چپ، روی آیکون Firebase کلیک کنید تا رابط کاربری افزونه Data Connect VS Code باز شود.

  1. روی دکمه‌ی «ورود با گوگل» کلیک کنید. یک پنجره‌ی مرورگر باز می‌شود؛ دستورالعمل‌ها را دنبال کنید تا با حساب گوگل خود وارد افزونه شوید.
  2. روی دکمه‌ی «اتصال به پروژه‌ی فایربیس» کلیک کنید و پروژه‌ای را که قبلاً در کنسول ایجاد کرده‌اید، انتخاب کنید.
  3. روی دکمه‌ی Run firebase init کلیک کنید و مراحل موجود در ترمینال یکپارچه را دنبال کنید.

پیکربندی تولید SDK

زمانی که روی دکمه‌ی Run firebase init کلیک کنید، افزونه‌ی Firebase Data Connect باید یک دایرکتوری dataconnect را برای شما مقداردهی اولیه کند.

در VS Code، فایل dataconnect/connector/connector.yaml را باز کنید، پیکربندی پیش‌فرض را خواهید یافت.

لطفاً پیکربندی را به‌روزرسانی کنید و از تنظیمات زیر استفاده کنید تا مطمئن شوید کد تولید شده با این codelab کار می‌کند. به‌طور خاص، مطمئن شوید که connectorId روی friendly-flix و پکیج Swift روی FriendlyFlixSDK تنظیم شده باشد.

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

منظور از این تنظیمات این است:

  • connectorId - یک نام منحصر به فرد برای این کانکتور.
  • outputDir - مسیری که SDK تولید شده Data Connect در آن ذخیره خواهد شد. این مسیر نسبت به دایرکتوری حاوی فایل connector.yaml است.
  • package - نام بسته‌ای که برای بسته Swift تولید شده استفاده می‌شود.

پس از ذخیره این فایل، Firebase Data Connect یک بسته Swift با نام FriendlyFlixSDK برای شما تولید می‌کند و آن را در کنار پوشه پروژه FriendlyFlix قرار می‌دهد.

شبیه‌سازهای Firebase را اجرا کنید

در VS Code، به نمای Firebase بروید و سپس روی دکمه‌ی Start emulators کلیک کنید.

این کار شبیه‌ساز Firebase را در ترمینال یکپارچه اجرا می‌کند. خروجی باید به شکل زیر باشد:

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

بسته تولید شده را به برنامه Swift خود اضافه کنید

  1. FriendlyFlix/app/FriendlyFlix/FriendlyFlix.xcodeproj را در Xcode باز کنید.
  2. فایل > افزودن وابستگی‌های بسته را انتخاب کنید...
  3. روی Add Local... کلیک کنید، سپس بسته FriendlyFlixSDK را از پوشه FriendlyFlix/app اضافه کنید.
  4. منتظر بمانید تا Xcode وابستگی‌های بسته را حل کند.
  5. در پنجره‌ی «انتخاب بسته‌ی محصولات برای FriendlyFlixSDK» ، FriendlyFlix به عنوان هدف انتخاب کنید و روی «افزودن بسته» کلیک کنید.

پیکربندی برنامه iOS برای استفاده از شبیه‌ساز محلی

  1. فایل FriendlyFlixApp.swift را باز کنید. (می‌توانید CMD + Shift + O را برای باز کردن کادر محاوره‌ای Quick Open فشار دهید و سپس برای یافتن سریع فایل، عبارت "FriendlyFlixApp" را تایپ کنید.)
  2. Firebase، Firebase Auth، Firebase Data Connect و SDK تولید شده برای طرحواره خود را وارد کنید
  3. در initialiser، Firebase را پیکربندی کنید.
  4. مطمئن شوید که 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()
  }

  ...

}
  1. یک شبیه‌ساز iOS را از منوی کشویی Destination انتخاب کنید.
  2. برای اجرای برنامه روی شبیه‌ساز، کلیدهای CMD+R را در Xcode فشار دهید (یا روی دکمه‌ی Run کلیک کنید).

۴. طرحواره را تعریف کنید و پایگاه داده را از قبل پر کنید

در این بخش، ساختار و روابط بین موجودیت‌های کلیدی در برنامه فیلم را در یک طرحواره تعریف خواهید کرد. موجودیت‌هایی مانند 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 هنگام ایجاد یک رکورد جدید پر می‌شود.

درج داده‌های ساختگی برای فیلم‌ها و فراداده‌های فیلم

با تعریف طرحواره، اکنون می‌توانید پایگاه داده را با داده‌های آزمایشی برای آزمایش از قبل پر کنید.

  1. در Finder، finish/FriendlyFlix/dataconnect/moviedata_insert.gql را در پوشه start/FriendlyFlix/dataconnect کپی کنید.
  2. در VS Code، dataconnect/moviedata_insert.gql را باز کنید.
  3. مطمئن شوید که شبیه‌سازها در افزونه‌ی Firebase Data Connect در حال اجرا هستند.
  4. شما باید دکمه‌ی «اجرا (محلی)» را در بالای فایل ببینید. برای وارد کردن داده‌های فیلم آزمایشی به پایگاه داده‌ی خود، روی این دکمه کلیک کنید.
  5. برای تأیید اینکه داده‌ها با موفقیت اضافه شده‌اند، ترمینال Data Connect Execution را بررسی کنید.

با قرار دادن داده‌ها در جای خود، به مرحله بعدی بروید تا نحوه ایجاد پرس‌وجوها در Data Connect را بیاموزید.

۵. بازیابی و نمایش فیلم‌ها

در این بخش، شما یک ویژگی برای نمایش لیستی از فیلم‌ها پیاده‌سازی خواهید کرد.

ابتدا، یاد خواهید گرفت که چگونه یک کوئری ایجاد کنید که تمام فیلم‌ها را از جدول movies بازیابی کند. Firebase Data Connect کدی را برای یک typesafe SDK تولید می‌کند که می‌توانید از آن برای اجرای کوئری و نمایش فیلم‌های بازیابی شده در رابط کاربری برنامه خود استفاده کنید.

کوئری ListMovies را تعریف کنید

کوئری‌ها در Firebase Data Connect با GraphQL نوشته شده‌اند و به شما امکان می‌دهند مشخص کنید کدام فیلدها را واکشی کنید. در FriendlyFlix، صفحاتی که فیلم‌ها را نمایش می‌دهند به فیلدهای زیر نیاز دارند: title ، description ، releaseYear ، rating و imageUrl . علاوه بر این، از آنجایی که این یک برنامه SwiftUI است، برای کمک به شناسایی نمای SwiftUI به id نیاز خواهید داشت.

در VS Code، فایل dataconnect/connector/queries.gql را باز کنید و کوئری ListMovies را اضافه کنید:

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

برای آزمایش کوئری جدید، روی دکمه‌ی Run (local) کلیک کنید تا کوئری روی پایگاه داده‌ی محلی شما اجرا شود. فهرست فیلم‌های موجود در پایگاه داده باید در بخش 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) ?? []
  }

  ...
}

کوئری listMoviesQuery() توسط Data Connect هنگام ذخیره queries.gql ایجاد شده است. برای مشاهده پیاده‌سازی Swift آن، فایل FriendlyFlixOperations.swift را در پکیج FriendlyFlixSDK بررسی کنید.

برنامه را اجرا کنید

در Xcode، روی دکمه‌ی Run کلیک کنید تا برنامه در شبیه‌ساز iOS اجرا شود.

پس از اجرای برنامه، باید صفحه‌ای شبیه به این را ببینید:

ممکن است متوجه شوید که تمام بخش‌های برنامه (بخش قهرمان، فیلم‌های برتر و فهرست تماشا) فهرست یکسانی را نشان می‌دهند. دلیل این امر این است که شما برای همه آن نماها از یک کوئری یکسان استفاده می‌کنید. در بخش‌های بعدی، کوئری‌های سفارشی را پیاده‌سازی خواهید کرد.

۶. نمایش فیلم‌های قهرمان و برتر

در این مرحله، شما بر به‌روزرسانی نحوه نمایش فیلم‌ها در بخش قهرمان - که همان چرخ و فلک برجسته در بالای صفحه اصلی است - و همچنین در بخش فیلم‌های برتر در زیر تمرکز خواهید کرد.

در حال حاضر، کوئری 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 را به‌روزرسانی کنید تا از این ویژگی‌های اضافی استفاده کنید.

از کوئری پیشرفته در رابط کاربری استفاده کنید

برای اعمال تغییرات لازم در HomeScreen.swift به Xcode برگردید.

ابتدا، heroMoviesRef را به‌روزرسانی کنید تا ۳ فیلم اخیراً منتشر شده را دریافت کنید:

struct HomeScreen {
  ...

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

  }
}

در مرحله بعد، یک مرجع پرس و جوی دیگر برای فیلم‌های برتر تنظیم کنید و فیلتر را روی ۵ فیلم با بالاترین امتیاز تنظیم کنید:

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) ?? []
  }

}

آن را در عمل ببینید

برنامه را دوباره اجرا کنید تا ۳ فیلم اخیر را در بخش قهرمان و ۵ فیلم با بالاترین امتیاز را در بخش فیلم‌های برتر ببینید:

۷. نمایش جزئیات فیلم و بازیگر

کاربر اکنون می‌تواند فیلم‌ها را مرور کند. وقتی روی کارت فیلم ضربه می‌زند، جزئیاتی در مورد فیلم به او نشان داده می‌شود، اما شاید متوجه شده باشید که این جزئیات فاقد مقدار مشخصی، خب... جزئیات هستند!

دلیلش این است که ما فقط جزئیاتی از هر فیلم را که برای رندر کردن بخش قهرمان فیلم و بخش فیلم‌های برتر نیاز داشتیم، دریافت کردیم: عنوان فیلم، توضیحات کوتاه و آدرس اینترنتی تصویر.

در صفحه جزئیات فیلم، می‌خواهیم اطلاعات بیشتری در مورد فیلم نشان دهیم. در این بخش، شما برنامه را طوری ارتقا می‌دهید که بتواند بازیگران فیلم و هرگونه نقد و بررسی را در صفحه جزئیات نشان دهد.

برای این کار، باید چند کار انجام دهید:

  • طرحواره را برای پشتیبانی از بازیگران فیلم و نقدها بهبود دهید
  • نوشتن کوئری‌های 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"
}

اضافه کردن داده‌های ساختگی برای بازیگران

با به‌روزرسانی طرحواره، اکنون می‌توانید پایگاه داده را با داده‌های آزمایشی بیشتری برای آزمایش پر کنید.

  1. در فایندر، finish/FriendlyFlix/dataconnect/moviededetails_insert.gql را در پوشه start/FriendlyFlix/dataconnect کپی کنید.
  2. در VS Code، dataconnect/moviededetails_insert.gql باز کنید.
  3. مطمئن شوید که شبیه‌سازها در افزونه‌ی Firebase Data Connect در حال اجرا هستند.
  4. شما باید دکمه‌ی «اجرا (محلی)» را در بالای فایل ببینید. برای وارد کردن داده‌های فیلم آزمایشی به پایگاه داده‌ی خود، روی این دکمه کلیک کنید.
  5. برای تأیید اینکه داده‌ها با موفقیت اضافه شده‌اند، ترمینال 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، روی دکمه‌ی Run کلیک کنید تا برنامه در شبیه‌ساز iOS اجرا شود.

پس از اجرای برنامه، روی کارت فیلم ضربه بزنید تا جزئیات فیلم نمایش داده شود. باید چیزی شبیه به این باشد:

۸. پیاده‌سازی احراز هویت کاربر

در حال حاضر، این برنامه اطلاعات فیلم و بازیگر را به صورت شخصی‌سازی نشده ارائه می‌دهد. در مراحل بعدی، ویژگی‌هایی را پیاده‌سازی خواهید کرد که داده‌ها را با کاربر وارد شده مرتبط می‌کنند. شما با اجازه دادن به کاربران برای اضافه کردن فیلم‌ها به فهرست تماشای شخصی خود شروع خواهید کرد.

قبل از اینکه بتوانید ویژگی watchlist را پیاده‌سازی کنید، ابتدا باید هویت کاربر را تعیین کنید. برای فعال کردن این قابلیت، احراز هویت 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 برای ثبت یک closure استفاده کنید که هنگام ورود کاربر فراخوانی می‌شود.

درون آن closure، می‌توانید یک حساب کاربری جدید در پایگاه داده ایجاد کنید. اما قبل از انجام این کار، باید یک mutation ایجاد کنید که به شما امکان ایجاد یا به‌روزرسانی کاربران جدید در پایگاه داده را بدهد.

یک موجودیت کاربر به طرحواره اضافه کنید

نوع 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 ایجاد می‌کند.
  • برای مشاهده همه کاربران در جدول users، روی Run local کلیک کنید.
  • در پنل Data Connect Execution، اکنون باید حسابی برای کاربری که با آن ثبت نام کرده‌اید، مشاهده کنید.

۹. فیلم‌های مورد علاقه‌تان را مدیریت کنید

در این بخش از آزمایشگاه کد، تعاملات کاربر را در برنامه نقد فیلم پیاده‌سازی خواهید کرد، به طور خاص به کاربران اجازه می‌دهید فیلم‌های مورد علاقه خود را مدیریت کنند. فیلم‌هایی که به عنوان موارد دلخواه علامت‌گذاری شده‌اند، در بخش فهرست تماشای برنامه نمایش داده می‌شوند.

طرحواره را برای پشتیبانی از موارد دلخواه بهبود دهید

نوع 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!
}

تعریف جهش‌ها برای اضافه کردن و حذف موارد دلخواه

قبل از اینکه برنامه بتواند فیلم‌های مورد علاقه کاربر را نمایش دهد، کاربر باید مشخص کند که کدام‌ها مورد علاقه او هستند . برای رسیدن به این هدف، ابتدا باید دو جهش اضافه کنید تا یک فیلم را به عنوان یکی از موارد دلخواه کاربر علامت‌گذاری کنید یا آن را دوباره از موارد دلخواه او حذف کنید.

  1. در VS Code، mutations.gql در dataconnect/connector/mutations.gql باز کنید.
  2. جهش‌های زیر را برای مدیریت فیلم‌های مورد علاقه اضافه کنید :
## 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 اعمال کنید:

  1. 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

  ...
}
  1. متد 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)
      }
    }
  }
}

این کار وضعیت مورد علاقه‌ی فیلم فعلی را در پایگاه داده به‌روزرسانی می‌کند. یک مرحله‌ی نهایی که جا افتاده این است که مطمئن شویم وضعیت رابط کاربری (UI) به طور مناسب منعکس شده است.

یک پرس‌وجو تعریف کنید تا بفهمید آیا یک فیلم به عنوان مورد علاقه علامت‌گذاری شده است یا خیر

  1. در VS Code، queries.gql در dataconnect/connector باز کنید.
  2. برای بررسی اینکه آیا یک فیلم به عنوان مورد علاقه علامت گذاری شده است یا خیر، کوئری زیر را اضافه کنید:
query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) {
  favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) {
    movieId
  }
}
  1. در 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
  }

  ...

}
  1. کد موجود در toggleFavourite را به‌روزرسانی کنید تا هر زمان که کاربر دکمه را لمس کرد، کوئری اجرا شود. این کار تضمین می‌کند که ویژگی محاسبه‌شده‌ی isFavourite همیشه مقدار صحیح را برمی‌گرداند.
  private func toggleFavourite() {
    Task {
      if isFavourite {
        ...
      }

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

فیلم‌های مورد علاقه را دریافت کنید

به عنوان آخرین مرحله برای این ویژگی، شما واکشی فیلم‌های مورد علاقه کاربر را پیاده‌سازی خواهید کرد تا بتواند آنها را در لیست تماشای خود ببیند.

  1. در 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 برنامه متصل خواهید کرد.

  1. کد را به نگاشت از 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
  }
}
  1. در Xcode، LibraryScreen را باز کنید، سپس isSignedIn به صورت زیر به‌روزرسانی کنید:
struct LibraryScreen: View {
  ...

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

}
  1. سپس، 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) ?? []
  }

  ...

}


  1. مطمئن شوید که کوئری watchListRef هنگام نمایش view اجرا می‌شود:
extension LibraryScreen: View {
  var body: some View {
    ...
            MovieListSection(namespace: namespace, title: "Watch List", movies: watchList)
              .onAppear {
                Task {
                  try await watchListRef.execute()
                }
  ...

آن را در عمل ببینید

اکنون می‌توانید برنامه را اجرا کنید و ویژگی مورد علاقه‌هایی که پیاده‌سازی کرده‌اید را امتحان کنید. چند نکته را باید در نظر داشته باشید:

  • مطمئن شوید که شبیه‌ساز Firebase در حال اجرا است
  • مطمئن شوید که داده‌های شبیه‌سازی‌شده برای فیلم‌ها و جزئیات فیلم را اضافه کرده‌اید
  • مطمئن شوید که به عنوان کاربر ثبت نام کرده‌اید
  1. در Xcode، روی دکمه‌ی Run کلیک کنید تا برنامه در شبیه‌ساز iOS اجرا شود.
  2. پس از اجرای برنامه، روی کارت فیلم ضربه بزنید تا جزئیات فیلم نمایش داده شود.
  3. برای علامت‌گذاری فیلم به عنوان مورد علاقه، روی نماد قلب ضربه بزنید. قلب باید به رنگ توپر درآید.
  4. این کار را برای چند فیلم تکرار کنید.
  5. به برگه کتابخانه بروید. اکنون باید لیستی از تمام فیلم‌هایی که به عنوان موارد دلخواه علامت‌گذاری کرده‌اید را ببینید.

۱۰. تبریک

تبریک می‌گوییم، شما با موفقیت Firebase Data Connect را به یک برنامه iOS اضافه کردید! اکنون مراحل کلیدی مورد نیاز برای راه‌اندازی Data Connect، ایجاد کوئری‌ها و جهش‌ها و مدیریت احراز هویت کاربر را می‌دانید.

اختیاری: استقرار در محیط عملیاتی

تاکنون این برنامه فقط از شبیه‌سازهای Firebase استفاده کرده است. اگر می‌خواهید نحوه‌ی استقرار این برنامه در یک پروژه‌ی Firebase واقعی را بیاموزید، به مرحله‌ی بعدی بروید.

۱۱. (اختیاری) برنامه خود را مستقر کنید

تاکنون این برنامه کاملاً محلی بوده است، تمام داده‌ها در مجموعه شبیه‌ساز Firebase موجود است. در این بخش یاد خواهید گرفت که چگونه پروژه Firebase خود را پیکربندی کنید تا این برنامه در محیط عملیاتی کار کند.

فعال کردن احراز هویت فایربیس

  1. در کنسول Firebase، به بخش Authentication بروید و روی Get started کلیک کنید.
  2. به برگه «روش ورود» بروید.
  3. گزینه ایمیل/رمز عبور را از بخش ارائه دهندگان بومی انتخاب کنید،
  4. ارائه دهنده ایمیل/رمز عبور را فعال کنید، سپس روی ذخیره کلیک کنید.

فعال کردن اتصال داده فایربیس

مهم: اگر این اولین باری است که یک طرحواره را در پروژه خود مستقر می‌کنید، این فرآیند یک نمونه Cloud SQL PostgreSQL ایجاد می‌کند که می‌تواند حدود ۱۵ دقیقه طول بکشد. تا زمانی که نمونه Cloud SQL آماده و با Firebase Data Connect یکپارچه نشود، نمی‌توانید آن را مستقر کنید.

۱. در رابط کاربری افزونه Firebase Data Connect VS Code، روی Deploy to production کلیک کنید. ۲. ممکن است لازم باشد تغییرات طرحواره را بررسی کرده و اصلاحات بالقوه مخرب را تأیید کنید. از شما خواسته می‌شود: - تغییرات طرحواره را با استفاده از firebase dataconnect:sql:diff بررسی کنید - وقتی از تغییرات راضی بودید، آنها را با استفاده از جریان آغاز شده توسط firebase dataconnect:sql:migrate اعمال کنید.

نمونه Cloud SQL برای PostgreSQL شما با طرحواره و داده‌های نهایی پیاده‌سازی شده به‌روزرسانی خواهد شد. می‌توانید وضعیت را در کنسول Firebase رصد کنید.

اکنون می‌توانید درست مانند کاری که با شبیه‌سازهای محلی انجام دادید، در پنل Firebase Data Connect روی Run (Production) کلیک کنید تا داده‌ها را به محیط تولید اضافه کنید.

قبل از اجرای مجدد برنامه iOS، مطمئن شوید که به نمونه عملیاتی پروژه شما متصل شده است:

  1. منوی محصول > طرحواره > ویرایش طرحواره... را باز کنید.
  2. در بخش Run ، تیک آرگومان -useEmulator YES launch‎ را بردارید.