۱. مرور کلی

به آزمایشگاه کدنویسی چت دوستانه خوش آمدید. در این آزمایشگاه کدنویسی، نحوه استفاده از پلتفرم Firebase برای ایجاد برنامههای iOS را خواهید آموخت. شما یک کلاینت چت پیادهسازی کرده و عملکرد آن را با استفاده از Firebase نظارت خواهید کرد.
آنچه یاد خواهید گرفت
- به کاربران اجازه ورود بدهید.
- همگامسازی دادهها با استفاده از پایگاه داده بلادرنگ Firebase.
- فایلهای باینری را در فضای ذخیرهسازی فایربیس ذخیره کنید.
آنچه نیاز دارید
- ایکسکد
- کوکوپادز
- یک دستگاه آزمایشی با iOS 8.0+ یا شبیهساز
چگونه از این آموزش استفاده خواهید کرد؟
تجربه خود را در ساخت اپلیکیشنهای iOS چگونه ارزیابی میکنید؟
۲. کد نمونه را دریافت کنید
مخزن گیتهاب را از خط فرمان کلون کنید.
$ git clone https://github.com/firebase/codelab-friendlychat-ios
۳. اپلیکیشن اولیه را بسازید

برای ساخت برنامه اولیه:
- در یک پنجره ترمینال، به مسیر زیر بروید
دایرکتوری ios-starter/swift-starterاز کد نمونهای که دانلود کردهاید -
pod install --repo-updateرا اجرا کنید. - فایل FriendlyChatSwift.xcworkspace را باز کنید تا پروژه در Xcode باز شود.
- کلیک کنید
دکمه اجرا .
باید بعد از چند ثانیه صفحه اصلی چت دوستانه ظاهر شود. رابط کاربری باید ظاهر شود. با این حال، در این مرحله نمیتوانید وارد سیستم شوید، پیام ارسال یا دریافت کنید. برنامه تا زمانی که مرحله بعدی را تکمیل نکنید، با یک استثنا متوقف میشود.
۴. یک پروژه Firebase راهاندازی کنید
ایجاد یک پروژه جدید فایربیس
- با استفاده از حساب گوگل خود وارد کنسول فایربیس شوید.
- برای ایجاد یک پروژه جدید، روی دکمه کلیک کنید و سپس نام پروژه را وارد کنید (برای مثال،
FriendlyChat). - روی ادامه کلیک کنید.
- در صورت درخواست، شرایط Firebase را مرور و قبول کنید و سپس روی ادامه کلیک کنید.
- (اختیاری) دستیار هوش مصنوعی را در کنسول Firebase (با نام "Gemini در Firebase") فعال کنید.
- برای این codelab، به گوگل آنالیتیکس نیاز ندارید ، بنابراین گزینه گوگل آنالیتیکس را غیرفعال کنید .
- روی ایجاد پروژه کلیک کنید، منتظر بمانید تا پروژه شما آماده شود و سپس روی ادامه کلیک کنید.
طرح قیمتگذاری فایربیس خود را ارتقا دهید
برای استفاده از فضای ذخیرهسازی ابری برای فایربیس، پروژه فایربیس شما باید در طرح قیمتگذاری پرداخت در محل (Blaze) باشد، به این معنی که به یک حساب پرداخت ابری متصل باشد.
- یک حساب Cloud Billing به یک روش پرداخت، مانند کارت اعتباری، نیاز دارد.
- اگر در استفاده از فایربیس و گوگل کلود تازهکار هستید، بررسی کنید که آیا واجد شرایط دریافت اعتبار ۳۰۰ دلاری و یک حساب کاربری رایگان ابری هستید یا خیر.
- اگر این codelab را به عنوان بخشی از یک رویداد انجام میدهید، از برگزارکننده خود بپرسید که آیا امکان استفاده از فضای ابری (Cloud credits) وجود دارد یا خیر.
برای ارتقاء پروژه خود به طرح Blaze، مراحل زیر را دنبال کنید:
- در کنسول Firebase، گزینه ارتقاء پلن خود را انتخاب کنید.
- طرح Blaze را انتخاب کنید. دستورالعملهای روی صفحه را دنبال کنید تا یک حساب Cloud Billing به پروژه شما متصل شود.
اگر به عنوان بخشی از این ارتقا نیاز به ایجاد یک حساب Cloud Billing داشتید، ممکن است لازم باشد برای تکمیل ارتقا، به روند ارتقا در کنسول Firebase برگردید.
برنامه iOS خود را وصل کنید
- از صفحه نمای کلی پروژه جدید خود، روی افزودن Firebase به برنامه iOS خود کلیک کنید.
- شناسه بسته را به صورت "
com.google.firebase.codelab.FriendlyChatSwift" وارد کنید. - شناسه اپ استور را «
123456» وارد کنید. - روی ثبت برنامه کلیک کنید.
فایل GoogleService-Info.plist را به برنامه خود اضافه کنید
در صفحه دوم، روی «دانلود GoogleService-Info.plist» کلیک کنید تا فایل پیکربندی حاوی تمام فرادادههای لازم Firebase برای برنامه شما دانلود شود. آن فایل را در برنامه خود کپی کنید و آن را به هدف FriendlyChatSwift اضافه کنید.
اکنون میتوانید روی «x» در گوشه سمت راست بالای پنجره کلیک کنید تا آن را ببندید - مراحل ۳ و ۴ را نادیده بگیرید - زیرا این مراحل را اینجا انجام خواهید داد.
ماژول فایربیس را وارد کنید
با اطمینان از وارد شدن ماژول Firebase شروع کنید.
AppDelegate.swift ، FCViewController.swift
import Firebase
پیکربندی Firebase در AppDelegate
از متد "configure" در FirebaseApp درون تابع application:didFinishLaunchingWithOptions برای پیکربندی سرویسهای اساسی Firebase از فایل .plist خود استفاده کنید.
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GIDSignIn.sharedInstance().delegate = self
return true
}
۵. کاربران را شناسایی کنید
از قوانین برای محدود کردن به کاربران احراز هویت شده استفاده کنید
اکنون قانونی اضافه خواهیم کرد تا قبل از خواندن یا نوشتن هر پیامی، احراز هویت الزامی شود. برای انجام این کار، قوانین زیر را به شیء داده پیامهای خود اضافه میکنیم. از بخش پایگاه داده کنسول Firebase، گزینه Realtime Database را انتخاب کنید، سپس روی تب Rules کلیک کنید. سپس قوانین را بهروزرسانی کنید تا به شکل زیر باشند:
{
"rules": {
"messages": {
".read": "auth != null",
".write": "auth != null"
}
}
}
برای اطلاعات بیشتر در مورد نحوهی کارکرد این قابلیت (از جمله مستندات مربوط به متغیر "auth") به مستندات امنیتی Firebase مراجعه کنید.
پیکربندی APIهای احراز هویت
قبل از اینکه برنامه شما بتواند از طرف کاربران به API های احراز هویت Firebase دسترسی پیدا کند، باید آن را فعال کنید.
- به کنسول Firebase بروید و پروژه خود را انتخاب کنید
- انتخاب احراز هویت
- برگه روش ورود را انتخاب کنید
- کلید گوگل را به حالت فعال (آبی) تغییر دهید
- در پنجرهی باز شده، روی ذخیره کلیک کنید.
اگر بعداً در این آزمایشگاه کد با خطایی با پیام "CONFIGURATION_NOT_FOUND" مواجه شدید، به این مرحله برگردید و کار خود را دوباره بررسی کنید.
وابستگی Firebase Auth را تأیید کنید
تأیید کنید که وابستگیهای Firebase Auth در فایل Podfile وجود دارند.
پادفایل
pod 'Firebase/Auth'
Info.plist خود را برای ورود به سیستم گوگل تنظیم کنید.
شما باید یک طرح URL سفارشی به پروژه XCode خود اضافه کنید.
- پیکربندی پروژه خود را باز کنید: روی نام پروژه در نمای درختی سمت چپ دوبار کلیک کنید. برنامه خود را از بخش TARGETS انتخاب کنید، سپس تب Info را انتخاب کنید و بخش URL Types را باز کنید.
- روی دکمه + کلیک کنید و یک طرح URL برای شناسه کلاینت معکوس شده خود اضافه کنید. برای یافتن این مقدار، فایل پیکربندی GoogleService-Info.plist را باز کنید و به دنبال کلید REVERSED_CLIENT_ID بگردید. مقدار آن کلید را کپی کرده و در کادر طرحهای URL در صفحه پیکربندی جایگذاری کنید. سایر فیلدها را خالی بگذارید.
- پس از تکمیل، پیکربندی شما باید چیزی شبیه به موارد زیر باشد (اما با مقادیر خاص برنامه شما):

تنظیم clientID برای ورود به سیستم گوگل
پس از پیکربندی Firebase، میتوانیم از clientID برای تنظیم ورود به سیستم گوگل در داخل متد "didFinishLaunchingWithOptions:" استفاده کنیم.
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
return true
}
افزودن کنترلکنندهی ورود
پس از موفقیتآمیز بودن نتیجهی ورود به سیستم گوگل، از حساب کاربری برای تأیید اعتبار با Firebase استفاده کنید.
AppDelegate.swift
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {
if let error = error {
print("Error \(error)")
return
}
guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
accessToken: authentication.accessToken)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
print("Error \(error)")
return
}
}
}
کاربر را به صورت خودکار وارد سیستم کنید. سپس یک شنونده به Firebase Auth اضافه کنید تا پس از ورود موفقیتآمیز، کاربر بتواند وارد برنامه شود. و شنونده را از deinit حذف کنید.
ورود به سیستم.SignInViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().signInSilently()
handle = Auth.auth().addStateDidChangeListener() { (auth, user) in
if user != nil {
MeasurementHelper.sendLoginEvent()
self.performSegue(withIdentifier: Constants.Segues.SignInToFp, sender: nil)
}
}
}
deinit {
if let handle = handle {
Auth.auth().removeStateDidChangeListener(handle)
}
}
خروج
متد خروج (Sign out) را اضافه کنید
FCViewController.swift
@IBAction func signOut(_ sender: UIButton) {
let firebaseAuth = Auth.auth()
do {
try firebaseAuth.signOut()
dismiss(animated: true, completion: nil)
} catch let signOutError as NSError {
print ("Error signing out: \(signOutError.localizedDescription)")
}
}
خواندن پیامها را به عنوان کاربر وارد شده آزمایش کنید
- کلیک کنید
دکمه اجرا . - شما باید فوراً به صفحه ورود هدایت شوید. روی دکمه ورود به سیستم با گوگل (Google Sign-In) ضربه بزنید.
- اگر همه چیز خوب پیش رفته باشد، باید به صفحه پیامرسانی هدایت شوید.
۶. پایگاه داده بلادرنگ را فعال کنید

وارد کردن پیامها
در پروژه خود در کنسول Firebase، آیتم Database را در نوار ناوبری سمت چپ انتخاب کنید. در منوی سرریز Database، گزینه Import JSON را انتخاب کنید. فایل initial_messages.json را در دایرکتوری friendlychat پیدا کنید، آن را انتخاب کنید و سپس روی دکمه Import کلیک کنید. این کار هر دادهای را که در حال حاضر در پایگاه داده شما وجود دارد، جایگزین میکند. همچنین میتوانید پایگاه داده را مستقیماً ویرایش کنید، با استفاده از + سبز و x قرمز برای اضافه کردن و حذف موارد.

بعد از ایمپورت کردن، دیتابیس شما باید به شکل زیر باشد:

وابستگی به پایگاه داده Firebase را تأیید کنید
در بلوک وابستگیهای فایل Podfile ، تأیید کنید که Firebase/Database گنجانده شده است.
پادفایل
pod 'Firebase/Database'
همگامسازی پیامهای موجود
کدی را اضافه کنید که پیامهای تازه اضافه شده را به رابط کاربری برنامه همگامسازی کند.
کدی که در این بخش اضافه میکنید:
- پایگاه داده Firebase را مقداردهی اولیه کنید و یک شنونده (listener) برای مدیریت تغییرات ایجاد شده در پایگاه داده اضافه کنید.
-
DataSnapshotرا بهروزرسانی کنید تا پیامهای جدید نمایش داده شوند.
متدهای "deinit"، "configureDatabase" و "tableView:cellForRow indexPath:" مربوط به FCViewController خود را تغییر دهید و آنها را با کد تعریف شده در زیر جایگزین کنید:
FCViewController.swift
deinit {
if let refHandle = _refHandle {
self.ref.child("messages").removeObserver(withHandle: _refHandle)
}
}
func configureDatabase() {
ref = Database.database().reference()
// Listen for new messages in the Firebase database
_refHandle = self.ref.child("messages").observe(.childAdded, with: { [weak self] (snapshot) -> Void in
guard let strongSelf = self else { return }
strongSelf.messages.append(snapshot)
strongSelf.clientTable.insertRows(at: [IndexPath(row: strongSelf.messages.count-1, section: 0)], with: .automatic)
})
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Dequeue cell
let cell = self.clientTable.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath)
// Unpack message from Firebase DataSnapshot
let messageSnapshot = self.messages[indexPath.row]
guard let message = messageSnapshot.value as? [String: String] else { return cell }
let name = message[Constants.MessageFields.name] ?? ""
let text = message[Constants.MessageFields.text] ?? ""
cell.textLabel?.text = name + ": " + text
cell.imageView?.image = UIImage(named: "ic_account_circle")
if let photoURL = message[Constants.MessageFields.photoURL], let URL = URL(string: photoURL),
let data = try? Data(contentsOf: URL) {
cell.imageView?.image = UIImage(data: data)
}
return cell
}
همگامسازی پیام آزمایشی
- کلیک کنید
دکمه اجرا . - برای رفتن به پنجره پیامها، روی دکمه « ورود برای شروع» کلیک کنید.
- با کلیک روی نماد + سبز رنگ کنار ورودی "messages" و افزودن شیء مانند زیر، پیامهای جدید را مستقیماً در کنسول Firebase اضافه کنید:

- تأیید کنید که آنها در رابط کاربری Friendly-Chat نمایش داده میشوند.
۷. ارسال پیام
پیادهسازی ارسال پیام
ارسال مقادیر به پایگاه داده. وقتی از متد push برای افزودن دادهها به پایگاه دادهی Realtime Firebase استفاده میکنید، یک شناسهی خودکار اضافه میشود. این شناسههای خودکار تولید شده، ترتیبی هستند که تضمین میکند پیامهای جدید به ترتیب صحیح اضافه شوند.
متد "sendMessage:" از FCViewController خود را تغییر دهید و آن را با کد تعریف شده زیر جایگزین کنید:
FCViewController.swift
func sendMessage(withData data: [String: String]) {
var mdata = data
mdata[Constants.MessageFields.name] = Auth.auth().currentUser?.displayName
if let photoURL = Auth.auth().currentUser?.photoURL {
mdata[Constants.MessageFields.photoURL] = photoURL.absoluteString
}
// Push data to Firebase Database
self.ref.child("messages").childByAutoId().setValue(mdata)
}
ارسال پیامها را آزمایش کنید
- کلیک کنید
دکمه اجرا . - برای رفتن به پنجره پیامها ، روی ورود کلیک کنید.
- یک پیام تایپ کنید و دکمه ارسال را بزنید. پیام جدید باید در رابط کاربری برنامه و کنسول Firebase قابل مشاهده باشد.
۸. ذخیره و دریافت تصاویر
وابستگی به فضای ذخیرهسازی فایربیس را تأیید کنید
در بلوک وابستگیهای Podfile ، تأیید کنید که Firebase/Storage گنجانده شده است.
پادفایل
pod 'Firebase/Storage'
راهاندازی فضای ذخیرهسازی ابری برای فایربیس
در اینجا نحوه تنظیم فضای ذخیرهسازی ابری برای فایربیس در پروژه فایربیس شما آورده شده است:
- در پنل سمت چپ کنسول Firebase، گزینه Build را باز کرده و سپس Storage را انتخاب کنید.
- روی شروع به کار کلیک کنید.
- مکانی را برای سطل ذخیرهسازی پیشفرض خود انتخاب کنید.
کاربران درUS-WEST1،US-CENTRAL1وUS-EAST1میتوانند از ردیف «همیشه رایگان» برای Google Cloud Storage بهرهمند شوند. کاربران در سایر مناطق ، از قیمتها و میزان استفاده از Google Cloud Storage پیروی میکنند. - روی شروع در حالت آزمایشی کلیک کنید. سلب مسئولیت مربوط به قوانین امنیتی را مطالعه کنید.
بعداً در این آزمایشگاه کد، قوانین امنیتی را برای ایمنسازی دادههای خود اضافه خواهید کرد. بدون اضافه کردن قوانین امنیتی برای مخزن ذخیرهسازی خود، برنامه را به صورت عمومی توزیع یا در معرض نمایش قرار ندهید . - روی ایجاد کلیک کنید.
پیکربندی FirebaseStorage
FCViewController.swift
func configureStorage() {
storageRef = Storage.storage().reference()
}
دریافت تصاویر در پیامهای موجود
کدی اضافه کنید که تصاویر را از Firebase Storage دانلود میکند.
متد "tableView: cellForRowAt indexPath:" در FCViewController خود را تغییر دهید و آن را با کد تعریف شده در زیر جایگزین کنید:
FCViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Dequeue cell
let cell = self.clientTable .dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath)
// Unpack message from Firebase DataSnapshot
let messageSnapshot: DataSnapshot! = self.messages[indexPath.row]
guard let message = messageSnapshot.value as? [String:String] else { return cell }
let name = message[Constants.MessageFields.name] ?? ""
if let imageURL = message[Constants.MessageFields.imageURL] {
if imageURL.hasPrefix("gs://") {
Storage.storage().reference(forURL: imageURL).getData(maxSize: INT64_MAX) {(data, error) in
if let error = error {
print("Error downloading: \(error)")
return
}
DispatchQueue.main.async {
cell.imageView?.image = UIImage.init(data: data!)
cell.setNeedsLayout()
}
}
} else if let URL = URL(string: imageURL), let data = try? Data(contentsOf: URL) {
cell.imageView?.image = UIImage.init(data: data)
}
cell.textLabel?.text = "sent by: \(name)"
} else {
let text = message[Constants.MessageFields.text] ?? ""
cell.textLabel?.text = name + ": " + text
cell.imageView?.image = UIImage(named: "ic_account_circle")
if let photoURL = message[Constants.MessageFields.photoURL], let URL = URL(string: photoURL),
let data = try? Data(contentsOf: URL) {
cell.imageView?.image = UIImage(data: data)
}
}
return cell
}
۹. ارسال پیامهای تصویری
پیادهسازی ذخیره و ارسال تصاویر
تصویری را از کاربر بارگذاری کنید، سپس آدرس اینترنتی محل ذخیرهسازی این تصویر را با پایگاه داده همگامسازی کنید تا این تصویر درون پیام ارسال شود.
متد "imagePickerController: didFinishPickingMediaWithInfo:" از FCViewController خود را تغییر دهید و آن را با کد تعریف شده در زیر جایگزین کنید:
FCViewController.swift
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : Any]) {
picker.dismiss(animated: true, completion:nil)
guard let uid = Auth.auth().currentUser?.uid else { return }
// if it's a photo from the library, not an image from the camera
if #available(iOS 8.0, *), let referenceURL = info[UIImagePickerControllerReferenceURL] as? URL {
let assets = PHAsset.fetchAssets(withALAssetURLs: [referenceURL], options: nil)
let asset = assets.firstObject
asset?.requestContentEditingInput(with: nil, completionHandler: { [weak self] (contentEditingInput, info) in
let imageFile = contentEditingInput?.fullSizeImageURL
let filePath = "\(uid)/\(Int(Date.timeIntervalSinceReferenceDate * 1000))/\((referenceURL as AnyObject).lastPathComponent!)"
guard let strongSelf = self else { return }
strongSelf.storageRef.child(filePath)
.putFile(from: imageFile!, metadata: nil) { (metadata, error) in
if let error = error {
let nsError = error as NSError
print("Error uploading: \(nsError.localizedDescription)")
return
}
strongSelf.sendMessage(withData: [Constants.MessageFields.imageURL: strongSelf.storageRef.child((metadata?.path)!).description])
}
})
} else {
guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else { return }
let imageData = UIImageJPEGRepresentation(image, 0.8)
let imagePath = "\(uid)/\(Int(Date.timeIntervalSinceReferenceDate * 1000)).jpg"
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
self.storageRef.child(imagePath)
.putData(imageData!, metadata: metadata) { [weak self] (metadata, error) in
if let error = error {
print("Error uploading: \(error)")
return
}
guard let strongSelf = self else { return }
strongSelf.sendMessage(withData: [Constants.MessageFields.imageURL: strongSelf.storageRef.child((metadata?.path)!).description])
}
}
}
ارسال و دریافت پیامهای تصویری را آزمایش کنید
- کلیک کنید
دکمه اجرا . - برای رفتن به پنجره پیامها ، روی ورود کلیک کنید.
- برای انتخاب عکس، روی آیکون «افزودن عکس» کلیک کنید. پیام جدید حاوی عکس باید در رابط کاربری برنامه و کنسول Firebase قابل مشاهده باشد.
۱۰. تبریک میگویم!
شما از Firebase برای ساخت آسان یک برنامه چت بلادرنگ استفاده کردهاید.
آنچه ما پوشش دادهایم
- پایگاه داده بلادرنگ
- ورود فدرال
- ذخیرهسازی
