1. סקירה כללית
טוב שהגעת ל-Face Chat Codelab. ב-Codelab הזה תלמדו איך להשתמש בפלטפורמת Firebase כדי ליצור אפליקציות ל-iOS. תלמדו איך להטמיע לקוח צ'אט ולנטר את הביצועים שלו באמצעות Firebase.
מה תלמדו
- המשתמשים יכולים להיכנס.
- סנכרון נתונים באמצעות Firebase Realtime Database.
- אחסון קבצים בינאריים ב-Firebase Storage.
מה צריך להכין
- Xcode
- CocoaPods
- מכשיר בדיקה עם iOS מגרסה 8.0 ואילך או סימולטור
איך תשתמשו במדריך הזה?
מהו הדירוג שלך לגבי חוויית הפיתוח של אפליקציות ל-iOS?
2. לקבלת הקוד לדוגמה
משכפלים את המאגר של GitHub משורת הפקודה.
$ git clone https://github.com/firebase/codelab-friendlychat-ios
3. פיתוח האפליקציה למתחילים
כדי ליצור את האפליקציה הבסיסית:
- בחלון מסוף, עוברים לספרייה
ios-starter/swift-starter
מההורדה של הקוד לדוגמה. - מריצים את
pod install --repo-update
- פותחים את הקובץ FriendlyChatSwift.xcworkspace כדי לפתוח את הפרויקט ב-Xcode.
- לוחצים על הלחצן Run.
אחרי כמה שניות אמור להופיע מסך הבית של Friendly Chat. ממשק המשתמש אמור להופיע. עם זאת, בשלב זה אין לך אפשרות להיכנס לחשבון, לשלוח או לקבל הודעות. האפליקציה תבוטל באופן חריג עד להשלמת השלב הבא.
4. יצירת פרויקט במסוף Firebase
יצירת פרויקט
במסוף Firebase, בוחרים באפשרות הוספת פרויקט.
נותנים לפרמטר הפרויקט שם (FriendlyChat
) ולוחצים על Create Project.
שדרוג של תוכנית התמחור ב-Firebase
כדי להשתמש ב-Cloud Storage for Firebase, הפרויקט ב-Firebase צריך להיות מוגדר לתוכנית תמחור ותשלומים לפי שימוש (Blaze), כלומר הוא מקושר לחשבון לחיוב ב-Cloud.
- בחשבון לחיוב ב-Cloud נדרש אמצעי תשלום, כמו כרטיס אשראי.
- אם אתם משתמשים חדשים ב-Firebase וב-Google Cloud, כדאי לבדוק אם אתם זכאים לקרדיט בסך 300$ ולחשבון לחיוב ב-Cloud בתקופת ניסיון בחינם.
- אם אתם עורכים את ה-Codelab כחלק מאירוע, כדאי לשאול את המארגן אם יש זיכויים ב-Cloud.
כדי לשדרג את הפרויקט לתוכנית Blaze, יש לפעול לפי השלבים הבאים:
- במסוף Firebase, בוחרים באפשרות שדרוג התוכנית.
- בוחרים את התוכנית Blaze. פועלים לפי ההוראות במסך כדי לקשר חשבון לחיוב ב-Cloud לפרויקט.
אם נדרשת יצירת חשבון לחיוב ב-Cloud כחלק מהשדרוג, יכול להיות שתצטרכו לחזור לתהליך השדרוג במסוף Firebase כדי להשלים את השדרוג.
חיבור האפליקציה ל-iOS
- במסך Project Overview (סקירה כללית של הפרויקט) של הפרויקט החדש, לוחצים על Add Firebase to your iOS app (הוספת Firebase לאפליקציה ל-iOS).
- יש להזין את מזהה החבילה כ-'
com.google.firebase.codelab.FriendlyChatSwift
'. - מזינים את מזהה App Store כ-'
123456
'. - לוחצים על רישום האפליקציה.
הוספת קובץ GoogleService-Info.plist לאפליקציה
במסך השני, לוחצים על Download GoogleService-Info.plist כדי להוריד קובץ תצורה שמכיל את כל המטא-נתונים הנדרשים של Firebase לאפליקציה. מעתיקים את הקובץ הזה לאפליקציה ומוסיפים אותו ליעד FriendlyChatSwift.
עכשיו אפשר ללחוץ על ה-"x" בפינה השמאלית העליונה של החלון הקופץ כדי לסגור אותו – לדלג על שלבים 3 ו-4 – ולבצע את השלבים האלה כאן.
מייבאים את מודול Firebase.
קודם כל מוודאים שהמודול 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
}
5. זיהוי משתמשים
שימוש בכללים כדי להגביל את הגישה למשתמשים מאומתים
עכשיו נוסיף כלל שידרוש אימות לפני קריאה או כתיבה של הודעות. כדי לעשות זאת, מוסיפים את הכללים הבאים לאובייקט הנתונים של ההודעות. בקטע Database (מסד נתונים) במסוף Firebase, בוחרים באפשרות Realtime Database (מסד נתונים בזמן אמת) ולוחצים על הכרטיסייה Rules (כללים). מעדכנים את הכללים כך שהם ייראו כך:
{
"rules": {
"messages": {
".read": "auth != null",
".write": "auth != null"
}
}
}
מידע נוסף על האופן שבו התהליך הזה פועל (כולל מסמכים על המשתנה auth) זמין במסמכי העזרה בנושא אבטחה של Firebase.
הגדרת ממשקי API לאימות
כדי שהאפליקציה תוכל לגשת ל-Firebase Authentication APIs בשם המשתמשים, תצטרכו להפעיל אותה.
- עוברים אל מסוף Firebase ובוחרים את הפרויקט.
- בוחרים באפשרות אימות.
- בוחרים בכרטיסייה שיטת כניסה.
- מחליפים את המצב של המתג של Google למצב מופעל (כחול)
- לוחצים על שמירה בתיבת הדו-שיח שנפתחת.
אם יופיעו שגיאות אחרות ב-Codelab הזה עם ההודעה "CONFIGURATION_NOT_FOUND", צריך לחזור לשלב הזה ולבדוק שוב את העבודה.
מוודאים שיש תלות ב-Firebase Auth
מוודאים שהקובץ Podfile
מכיל יחסי תלות של Firebase Auth.
Podfile
pod 'Firebase/Auth'
מגדירים את Info.plist לכניסה באמצעות חשבון Google.
צריך להוסיף סכימה של כתובת URL מותאמת אישית לפרויקט XCode.
- פותחים את הגדרות הפרויקט: לוחצים לחיצה כפולה על שם הפרויקט בתצוגת העץ הימנית. בוחרים את האפליקציה בקטע 'יעדים', ואז בוחרים בכרטיסייה 'פרטים' ומרחיבים את הקטע 'סוגי כתובות URL'.
- לוחצים על הלחצן + ומוסיפים סכימה של כתובת URL למזהה הלקוח ההפוך. כדי למצוא את הערך הזה, פותחים את קובץ התצורה GoogleService-Info.plist ומחפשים את המפתח REVERSED_CLIENT_ID. מעתיקים את הערך של המפתח ומדביקים אותו בתיבה 'סכמות של כתובות URL' בדף התצורה. משאירים את שאר השדות ריקים.
- בסיום, קובץ התצורה אמור להיראות בערך כך (אבל עם הערכים הספציפיים לאפליקציה שלכם):
הגדרת ClientID לכניסה באמצעות חשבון Google
אחרי שמגדירים את Firebase, אפשר להשתמש ב-clientID כדי להגדיר את הכניסה באמצעות חשבון Google בתוך השיטה 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
}
הוספת הטיפול בכניסה
אחרי שהתוצאה של הכניסה באמצעות חשבון Google תהיה מוצלחת, תוכלו להשתמש בחשבון כדי לבצע אימות באמצעות 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 כדי לאפשר למשתמש להיכנס לאפליקציה אחרי כניסה מוצלחת. ולהסיר את המאזינים מ-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)
}
}
יציאה
הוספת שיטת היציאה
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'.
- אם הכול עבד בצורה טובה, המערכת אמורה להעביר אתכם למסך ההודעות.
6. הפעלת מסד נתונים בזמן אמת
ייבוא הודעות
בפרויקט במסוף Firebase, בוחרים את הפריט מסד נתונים בסרגל הניווט הימני. בתפריט האפשרויות הנוספות של מסד הנתונים, בוחרים באפשרות ייבוא JSON. מאתרים את הקובץ initial_messages.json
בספריית ידידותיות לצ'אט, בוחרים אותו ולוחצים על הלחצן ייבוא. הפעולה הזו תחליף את כל הנתונים שנמצאים כרגע במסד הנתונים. אפשר גם לערוך את מסד הנתונים ישירות, באמצעות הסמל '+' הירוק והסמל 'x' האדום כדי להוסיף ולהסיר פריטים.
בסיום הייבוא, מסד הנתונים אמור להיראות כך:
בדיקת התלות של מסד הנתונים ב-Firebase
בבלוק של יחסי התלות בקובץ Podfile
, מוודאים ש-Firebase/Database
נכלל.
Podfile
pod 'Firebase/Database'
סנכרון ההודעות הקיימות
מוסיפים קוד שמסנכרן הודעות חדשות שנוספו לממשק המשתמש של האפליקציה.
הקוד שתוסיפו בקטע הזה:
- מאתחלים את מסד הנתונים של Firebase ומוסיפים מאזין לטיפול בשינויים שבוצעו במסד הנתונים.
- מעדכנים את
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
}
בדיקת סנכרון ההודעות
- לוחצים על הלחצן Run.
- לוחצים על הלחצן כניסה כדי להתחיל כדי לעבור לחלון ההודעות.
- כדי להוסיף הודעות חדשות ישירות במסוף Firebase, לוחצים על הסמל הירוק + לצד הרשומה messages ומוסיפים אובייקט כמו זה:
- מוודאים שהם מופיעים בממשק המשתמש של Friendly-Chat.
7. שליחת הודעות
הטמעת Send Message
דחיפת ערכים למסד הנתונים. כשמשתמשים בשיטת ה-push כדי להוסיף נתונים ל-Firebase Realtime Database, המערכת מוסיפה מזהה אוטומטי. המזהים האלה שנוצרים באופן אוטומטי הם רציפים, וכך אפשר להבטיח שהודעות חדשות יתווספו בסדר הנכון.
משנים את שיטת "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)
}
בדיקת שליחת הודעות
- לוחצים על הלחצן Run.
- לוחצים על כניסה כדי לעבור לחלון ההודעות.
- מקלידים הודעה ומקישים על סמל השליחה. ההודעה החדשה אמורה להופיע בממשק המשתמש של האפליקציה ובמסוף Firebase.
8. אחסון וקבלה של תמונות
בדיקה של תלות האחסון ב-Firebase
בבלוק יחסי התלות של Podfile
, מוודאים ש-Firebase/Storage
נכלל.
Podfile
pod 'Firebase/Storage'
הגדרת Cloud Storage for Firebase
כך מגדירים את Cloud Storage for Firebase בפרויקט Firebase:
- בחלונית השמאלית של מסוף Firebase, מרחיבים את Build ובוחרים באפשרות Storage (אחסון).
- לוחצים על תחילת העבודה.
- יש לבחור מיקום לקטגוריית האחסון המוגדרת כברירת מחדל.
קטגוריות ב-US-WEST1
, ב-US-CENTRAL1
וב-US-EAST1
יכולות לנצל את המסלול 'חינם תמיד' ל-Google Cloud Storage. קטגוריות בכל המיקומים האחרים כפופות לתמחור ולשימוש ב-Google Cloud Storage. - לוחצים על התחלה במצב בדיקה. צריך לקרוא את כתב הוויתור לגבי כללי האבטחה.
בהמשך ב-Codelab הזה יתווסף כללי אבטחה לאבטחת הנתונים שלך. לא תפיץ או תחשוף אפליקציה באופן ציבורי בלי להוסיף כללי אבטחה לקטגוריית האחסון שלכם. - לוחצים על יצירה.
הגדרת 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
}
9. שליחת הודעות תמונה
הטמעה של חנות ושליחה של תמונות
צריך להעלות תמונה מהמשתמש, ואז לסנכרן את כתובת ה-URL של אחסון התמונה הזו למסד הנתונים כדי שהתמונה תישלח בתוך ההודעה.
משנים את השיטה '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])
}
}
}
איך לבדוק שליחה וקבלה של הודעות תמונה
- לוחצים על הלחצן Run.
- לוחצים על כניסה כדי לעבור לחלון ההודעות.
- לוחצים על הסמל 'הוספת תמונה' כדי לבחור תמונה. ההודעה החדשה עם התמונה צריכה להופיע בממשק המשתמש של האפליקציה ובמסוף Firebase.
10. כל הכבוד!
השתמשתם ב-Firebase כדי ליצור בקלות אפליקציית צ'אט בזמן אמת.
אילו נושאים דיברנו?
- מסד נתונים בזמן אמת
- כניסה מאוחדת
- אחסון