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

1. بررسی اجمالی

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

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

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

چیزی که یاد خواهید گرفت

این کد لبه به شما یاد می دهد که چگونه:

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

پیش نیازها

  • آخرین نسخه Xcode
  • کد نمونه کد لبه. نمونه کد را در یکی از اولین مراحل نرم افزار Codelab دانلود خواهید کرد.

2. پروژه نمونه را راه اندازی کنید

یک پروژه Firebase ایجاد کنید

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

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

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

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

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

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

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

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

3. Data Connect را راه اندازی کنید

نصب و راه اندازی

نصب خودکار

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

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

این اسکریپت سعی می کند محیط توسعه را برای شما تنظیم کند و یک IDE مبتنی بر مرورگر راه اندازی کند. این IDE ابزارهایی از جمله یک پسوند کد VS از پیش همراه را ارائه می دهد تا به شما کمک کند طرحواره خود را مدیریت کنید و پرس و جوها و جهش هایی را برای استفاده در برنامه خود تعریف کنید و 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. روی دکمه Sign in with Google کلیک کنید. یک پنجره مرورگر باز می شود؛ دستورالعمل ها را دنبال کنید تا با حساب Google خود به برنامه افزودنی وارد شوید.
  2. روی دکمه Connect a Firebase project کلیک کنید و پروژه ای را که قبلا در کنسول ایجاد کردید انتخاب کنید.
  3. روی دکمه 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 یک بسته سوئیفت به نام FriendlyFlixSDK برای شما تولید می کند و آن را در کنار پوشه پروژه FriendlyFlix قرار می دهد.

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

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

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

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

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

  1. FriendlyFlix/app/FriendlyFlix/FriendlyFlix.xcodeproj را در Xcode باز کنید
  2. File > Add Package Dependencies را انتخاب کنید...
  3. روی Add Local... کلیک کنید، سپس بسته FriendlyFlixSDK را از پوشه FriendlyFlix/app اضافه کنید.
  4. منتظر بمانید تا Xcode وابستگی های بسته را برطرف کند.
  5. در گفتگوی Choose Package Products for FriendlyFlixSDK ، FriendlyFlix به عنوان هدف انتخاب کنید و روی Add Package کلیک کنید.

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

  1. FriendlyFlixApp.swift را باز کنید. (می توانید CMD + Shift + O را فشار دهید تا پنجره باز کردن سریع باز شود و سپس «FriendlyFlixApp» را تایپ کنید تا فایل را سریع پیدا کنید)
  2. Firebase، Firebase Auth، Firebase Data Connect و SDK ایجاد شده را برای طرح شما وارد کنید
  3. در آغازگر، 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 را فشار دهید (یا روی دکمه 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 پر می شود که یک رکورد جدید ایجاد شود.

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

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

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

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

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

در این قسمت قابلیت نمایش لیست فیلم ها را پیاده سازی خواهید کرد.

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

  ...
}

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

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

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

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

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

ابتدا 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
      }
  }
}

در نهایت، ویژگی محاسبه شده را که نتیجه این کوئری را به UI متصل می کند، به روز کنید:

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"
}

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

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

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

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

8. احراز هویت کاربر را پیاده سازی کنید

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

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

شاید قبلاً دکمه آواتار کاربر را در سمت راست بالای صفحه اصلی مشاهده کرده باشید. با زدن این گزینه شما را به صفحه ای هدایت می کند که در آن کاربران می توانند با استفاده از ایمیل و رمز عبور خود ثبت نام کرده یا وارد سیستم شوند.

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

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

در کنسول Firebase برای پروژه خود، به بخش Authentication بروید و Firebase Authentication را فعال کنید. سپس، ارائه دهنده احراز هویت ایمیل/رمز عبور را فعال کنید.

در پوشه پروژه محلی خود، firebase.json پیدا کنید و آن را به صورت زیر به روز کنید تا شبیه ساز Firebase Authentication فعال شود.

{
  "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 Authentication ثبت نام کرد، یک کاربر جدید را وارد کنید (یا یک کاربر موجود را با همان شناسه به روز کنید).

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

برای تأیید اینکه این کار می کند، ابتدا در برنامه iOS ثبت نام کنید:

  • اگر این کار را نکرده اید، شبیه ساز Firebase را متوقف کرده و مجددا راه اندازی کنید تا مطمئن شوید که شبیه ساز احراز هویت Firebase در حال اجرا است.
  • در Xcode، روی دکمه Run کلیک کنید تا برنامه در شبیه ساز iOS اجرا شود.
  • روی نماد آواتار در گوشه سمت راست بالای صفحه کلیک کنید.
  • به جریان ثبت نام بروید و در برنامه ثبت نام کنید.

سپس، از پایگاه داده پرس و جو کنید تا تأیید کنید که برنامه یک حساب کاربری جدید برای کاربر ایجاد کرده است:

  • در VS Code، dataconnect/schema/schema.gql باز کنید و روی Read data در موجودیت User کلیک کنید.
  • این یک فایل پرس و جو جدید به نام User_read.gql ایجاد می کند
  • روی Run local کلیک کنید تا همه کاربران در جدول کاربران را ببینید
  • در پنجره Data Connect Execution، اکنون باید یک حساب کاربری را ببینید که به تازگی با آن ثبت نام کرده اید.

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!
}

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

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

  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)
      }
    }
  }
}

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

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

  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 زمانی که نمای ظاهر می شود اجرا می شود:
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. به تب Library بروید. اکنون باید لیستی از تمام فیلم هایی که به عنوان موارد دلخواه علامت گذاری کرده اید را مشاهده کنید.

10. تبریک می گویم

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

اختیاری: استقرار در تولید

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

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

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

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

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

Firebase Data Connect را فعال کنید

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

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

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

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

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

  1. منوی Product > Scheme > Edit Scheme... را باز کنید.
  2. در بخش Run تیک آرگومان راه اندازی -useEmulator YES را بردارید.