Firebase iOS Codelab Swift

1. نظرة عامة

2efe6805ef369641.png

مرحبًا بك في الدرس التطبيقي لبرمجة الدردشة الودية. ستتعلم في هذا الدرس التدريبي حول البرمجة كيفية استخدام منصة Firebase لإنشاء تطبيقات iOS. ستقوم بتنفيذ عميل الدردشة ومراقبة أدائه باستخدام Firebase.

ما ستتعلمه

  • السماح للمستخدمين بتسجيل الدخول.
  • مزامنة البيانات باستخدام قاعدة بيانات Firebase Realtime.
  • تخزين الملفات الثنائية في Firebase Storage.

ماذا ستحتاج

  • Xcode
  • كاكاوبودس
  • جهاز اختبار يعمل بنظام iOS 8.0+ أو جهاز محاكاة

كيف ستستخدم هذا البرنامج التعليمي؟

اقرأها من خلال فقط اقرأها وأكمل التمارين

كيف تقيم تجربتك في بناء تطبيقات iOS؟

مبتدئ متوسط بارع

2. احصل على نموذج التعليمات البرمجية

استنساخ مستودع GitHub من سطر الأوامر.

$ git clone https://github.com/firebase/codelab-friendlychat-ios

3. قم بإنشاء تطبيق البداية

2f4c98d858c453fe.png

لإنشاء التطبيق المبدئي:

  1. في النافذة الطرفية، انتقل إلى android_studio_folder.png دليل ios-starter/swift-starter من تنزيل نموذج التعليمات البرمجية الخاص بك
  2. قم بتشغيل pod install --repo-update
  3. افتح ملف FriendlyChatSwift.xcworkspace لفتح المشروع في Xcode.
  4. انقر على 98205811bbed9d74.png زر التشغيل .

من المفترض أن تظهر شاشة الدردشة الودية الرئيسية بعد بضع ثوانٍ. يجب أن تظهر واجهة المستخدم. ومع ذلك، في هذه المرحلة لا يمكنك تسجيل الدخول أو إرسال أو استقبال الرسائل. سيتم إحباط التطبيق باستثناء حتى تكمل الخطوة التالية.

4. إنشاء مشروع وحدة تحكم Firebase

إنشاء مشروع

من وحدة تحكم Firebase، حدد إضافة مشروع .

اتصل بالمشروع FriendlyChat ، ثم انقر فوق "إنشاء مشروع" .

لقطة شاشة من 2015-11-06 14:13:39.png

قم بتوصيل تطبيق iOS الخاص بك

  1. من شاشة "نظرة عامة على المشروع" لمشروعك الجديد، انقر فوق "إضافة Firebase إلى تطبيق iOS" الخاص بك .
  2. أدخل معرف الحزمة، مثل " com.google.firebase.codelab.FriendlyChatSwift ".
  3. أدخل معرف متجر التطبيقات كـ " 123456 ".
  4. انقر فوق تسجيل التطبيق .

أضف ملف GoogleService-Info.plist إلى تطبيقك

في الشاشة الثانية، انقر فوق Download GoogleService-Info.plist لتنزيل ملف التكوين الذي يحتوي على جميع بيانات تعريف Firebase الضرورية لتطبيقك. انسخ هذا الملف إلى تطبيقك وأضفه إلى هدف FriendlyChatSwift .

يمكنك الآن النقر فوق "x" في الزاوية اليمنى العليا من النافذة المنبثقة لإغلاقها - تخطي الخطوتين 3 و4 - حيث ستقوم بتنفيذ هذه الخطوات هنا.

19d59efb213ddbdc.png

استيراد وحدة Firebase

ابدأ بالتأكد من استيراد وحدة Firebase .

AppDelegate.swift ، FCViewController.swift

import Firebase

تكوين Firebase في AppDelegate

استخدم طريقة "التكوين" في FirebaseApp داخل التطبيق: وظيفة didFinishLaunchingWithOptions لتكوين خدمات Firebase الأساسية من ملف .plist الخاص بك.

AppDelegate.swift

  func application(_ application: UIApplication, didFinishLaunchingWithOptions
      launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  FirebaseApp.configure()
  GIDSignIn.sharedInstance().delegate = self
  return true
}

5. تحديد المستخدمين

استخدم القواعد لتقييد المستخدمين المصادق عليهم

سنضيف الآن قاعدة تتطلب المصادقة قبل قراءة أو كتابة أي رسائل. للقيام بذلك، نضيف القواعد التالية إلى كائن بيانات الرسائل الخاص بنا. من داخل قسم قاعدة البيانات في وحدة تحكم Firebase، حدد Realtime Database، ثم انقر فوق علامة التبويب "القواعد". ثم قم بتحديث القواعد بحيث تبدو كما يلي:

{
  "rules": {
    "messages": {
      ".read": "auth != null",
      ".write": "auth != null"
    }
  }
}

لمزيد من المعلومات حول كيفية عمل ذلك (بما في ذلك الوثائق المتعلقة بالمتغير "auth")، راجع وثائق أمان Firebase.

تكوين واجهات برمجة تطبيقات المصادقة

قبل أن يتمكن تطبيقك من الوصول إلى واجهات برمجة تطبيقات مصادقة Firebase نيابةً عن المستخدمين لديك، سيتعين عليك تمكينه

  1. انتقل إلى وحدة تحكم Firebase وحدد مشروعك
  2. حدد المصادقة
  3. حدد علامة التبويب طريقة تسجيل الدخول
  4. تبديل مفتاح Google إلى الوضع الممكّن (الأزرق)
  5. اضغط على حفظ في مربع الحوار الناتج

إذا ظهرت لك أخطاء لاحقًا في هذا الدرس التطبيقي حول الترميز مع الرسالة "CONFIGURATION_NOT_FOUND"، فارجع إلى هذه الخطوة وتحقق جيدًا من عملك.

تأكيد تبعية Firebase Auth

تأكد من وجود تبعيات Firebase Auth في ملف Podfile .

ملف بودفي

pod 'Firebase/Auth'

قم بإعداد Info.plist لتسجيل الدخول إلى Google.

ستحتاج إلى إضافة نظام URL مخصص إلى مشروع XCode الخاص بك.

  1. افتح تكوين مشروعك: انقر نقرًا مزدوجًا فوق اسم المشروع في عرض الشجرة الأيسر. حدد تطبيقك من قسم TARGETS، ثم حدد علامة تبويب المعلومات، وقم بتوسيع قسم أنواع URL.
  2. انقر فوق الزر +، وأضف نظام URL لمعرف العميل المعكوس. للعثور على هذه القيمة، افتح ملف تكوين GoogleService-Info.plist، وابحث عن مفتاح REVERSED_CLIENT_ID. انسخ قيمة هذا المفتاح، وألصقها في مربع مخططات URL في صفحة التكوين. اترك الحقول الأخرى فارغة.
  3. عند الانتهاء، يجب أن يبدو التكوين الخاص بك مشابهًا لما يلي (ولكن مع القيم الخاصة بالتطبيق):

1b54d5bd2f4f1448.png

قم بتعيين معرف العميل لتسجيل الدخول إلى Google

بعد تهيئة Firebase، يمكننا استخدام معرف العميل لإعداد تسجيل الدخول إلى 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 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)
    }
  }

خروج

أضف طريقة تسجيل الخروج

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

اختبار قراءة الرسائل كمستخدم مسجل الدخول

  1. انقر على 98205811bbed9d74.png زر التشغيل .
  2. يجب أن يتم إرسالك على الفور إلى شاشة تسجيل الدخول. اضغط على زر تسجيل الدخول بجوجل.
  3. من المفترض بعد ذلك أن يتم إرسالك إلى شاشة المراسلة إذا كان كل شيء يعمل بشكل جيد.

6. تفعيل قاعدة البيانات في الوقت الحقيقي

2efe6805ef369641.png

استيراد الرسائل

في مشروعك في وحدة تحكم Firebase، حدد عنصر قاعدة البيانات على شريط التنقل الأيسر. في القائمة الكاملة لقاعدة البيانات، حدد Import JSON . قم بالتصفح للوصول إلى الملف initial_messages.json الموجود في دليل الدردشة الودية، ثم حدده ثم انقر فوق الزر "استيراد" . سيؤدي هذا إلى استبدال أي بيانات موجودة حاليًا في قاعدة بياناتك. يمكنك أيضًا تحرير قاعدة البيانات مباشرةً، باستخدام علامة + الخضراء وعلامة x الحمراء لإضافة العناصر وإزالتها.

20ccf4856b715b4c.png

بعد استيراد قاعدة البيانات الخاصة بك يجب أن تبدو كما يلي:

f3e0367f1c9cd187.png

تأكيد تبعية قاعدة بيانات Firebase

في كتلة التبعيات لملف Podfile ، تأكد من تضمين Firebase/Database .

ملف بودفي

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
  }

اختبار مزامنة الرسائل

  1. انقر على 98205811bbed9d74.png زر التشغيل .
  2. انقر فوق الزر تسجيل الدخول للبدء للانتقال إلى نافذة الرسائل.
  3. أضف رسائل جديدة مباشرة في وحدة تحكم Firebase من خلال النقر على الرمز الأخضر + بجوار إدخال "الرسائل" وإضافة كائن مثل ما يلي: f9876ffc8b316b14.png
  4. تأكد من ظهورهم في واجهة مستخدم الدردشة الودية.

7. إرسال الرسائل

تنفيذ إرسال رسالة

دفع القيم إلى قاعدة البيانات. عند استخدام طريقة الدفع لإضافة البيانات إلى قاعدة بيانات Firebase Realtime، ستتم إضافة معرف تلقائي. تكون هذه المعرفات التي تم إنشاؤها تلقائيًا متسلسلة، مما يضمن إضافة الرسائل الجديدة بالترتيب الصحيح.

تعديل طريقة "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)
  }

اختبار إرسال الرسائل

  1. انقر على 98205811bbed9d74.png زر التشغيل .
  2. انقر فوق تسجيل الدخول للانتقال إلى نافذة الرسائل.
  3. اكتب رسالة واضغط على إرسال. يجب أن تكون الرسالة الجديدة مرئية في واجهة مستخدم التطبيق وفي وحدة تحكم Firebase.

8. تخزين واستقبال الصور

تأكيد تبعية تخزين Firebase

في كتلة التبعيات في Podfile ، تأكد من تضمين Firebase/Storage .

ملف بودفي

pod 'Firebase/Storage'

قم بتنشيط تخزين Firebase في لوحة القيادة

انتقل إلى وحدة تحكم Firebase وتأكد من تنشيط التخزين باستخدام المجال "gs://PROJECTID.appspot.com"

b0438b37a588bcee.png

إذا كنت ترى نافذة التنشيط بدلاً من ذلك، فانقر فوق "البدء" لتنشيطها باستخدام القواعد الافتراضية.

c290bbebff2cafa7.png

تكوين 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])
      }
    }
  }

اختبار إرسال واستقبال الرسائل المصورة

  1. انقر على 98205811bbed9d74.png زر التشغيل .
  2. انقر فوق تسجيل الدخول للانتقال إلى نافذة الرسائل.
  3. انقر على أيقونة "إضافة صورة" لاختيار صورة. يجب أن تكون الرسالة الجديدة التي تحتوي على الصورة مرئية في واجهة مستخدم التطبيق وفي وحدة تحكم Firebase.

10. تهانينا!

لقد استخدمت Firebase لإنشاء تطبيق دردشة في الوقت الفعلي بسهولة.

ما قمنا بتغطيته

  • قاعدة بيانات الوقت الحقيقي
  • تسجيل الدخول الموحد
  • تخزين

يتعلم أكثر