Codelab Firebase iOS Swift

1. Ringkasan

2efe6805ef369641.png

Selamat datang di codelab Friendly Chat. Dalam codelab ini, Anda akan mempelajari cara menggunakan platform Firebase untuk membuat aplikasi iOS. Anda akan menerapkan klien chat dan memantau performanya menggunakan Firebase.

Hal yang akan Anda pelajari

  • Izinkan pengguna login.
  • Sinkronkan data menggunakan Firebase Realtime Database.
  • Simpan file biner di Firebase Storage.

Hal yang akan Anda perlukan

  • Xcode
  • CocoaPods
  • Perangkat pengujian dengan iOS 8.0+ atau simulator

Bagaimana Anda akan menggunakan tutorial ini?

Hanya membacanya Membacanya dan menyelesaikan latihan

Bagaimana Anda menilai pengalaman membuat aplikasi iOS Anda?

Pemula Menengah Mahir

2. Mendapatkan kode contoh

Buat clone repositori GitHub dari command line.

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

3. Membangun aplikasi awal

2f4c98d858c453fe.png

Untuk membangun aplikasi awal:

  1. Di jendela terminal, buka direktori android_studio_folder.pngios-starter/swift-starter dari download kode contoh Anda
  2. Jalankan pod install --repo-update
  3. Buka file FriendlyChatSwift.xcworkspace untuk membuka project di Xcode.
  4. Klik tombol 98205811bbed9d74.pngRun.

Anda akan melihat layar utama Friendly Chat muncul setelah beberapa detik. UI akan muncul. Namun, pada tahap ini Anda tidak dapat login, mengirim, atau menerima pesan. Aplikasi akan dibatalkan dengan pengecualian hingga Anda menyelesaikan langkah berikutnya.

4. Menyiapkan project Firebase

Membuat project Firebase baru

  1. Login ke Firebase console menggunakan Akun Google Anda.
  2. Klik tombol untuk membuat project baru, lalu masukkan nama project (misalnya, FriendlyChat).
  3. Klik Lanjutkan.
  4. Jika diminta, tinjau dan setujui persyaratan Firebase, lalu klik Continue.
  5. (Opsional) Aktifkan bantuan AI di Firebase console (disebut "Gemini di Firebase").
  6. Untuk codelab ini, Anda tidak memerlukan Google Analytics, jadi nonaktifkan opsi Google Analytics.
  7. Klik Buat project, tunggu hingga project Anda disediakan, lalu klik Lanjutkan.

Mengupgrade paket harga Firebase

Untuk menggunakan Cloud Storage for Firebase, project Firebase Anda harus menggunakan paket harga bayar sesuai penggunaan (Blaze), yang berarti project tersebut ditautkan ke akun Penagihan Cloud.

  • Akun Penagihan Cloud memerlukan metode pembayaran, seperti kartu kredit.
  • Jika Anda baru menggunakan Firebase dan Google Cloud, periksa apakah Anda memenuhi syarat untuk mendapatkan kredit sebesar$300 dan akun Penagihan Cloud Uji Coba Gratis.
  • Jika Anda melakukan codelab ini sebagai bagian dari acara, tanyakan kepada penyelenggara apakah ada kredit Cloud yang tersedia.

Untuk mengupgrade project Anda ke paket Blaze, ikuti langkah-langkah berikut:

  1. Di Firebase console, pilih upgrade your plan.
  2. Pilih paket Blaze. Ikuti petunjuk di layar untuk menautkan akun Penagihan Cloud ke project Anda.
    Jika perlu membuat akun Penagihan Cloud sebagai bagian dari upgrade ini, Anda mungkin perlu kembali ke alur upgrade di Firebase console untuk menyelesaikan upgrade.

Menghubungkan aplikasi iOS

  1. Dari layar Project Overview project baru Anda, klik Tambahkan Firebase ke aplikasi iOS Anda.
  2. Masukkan ID paket, sebagai "com.google.firebase.codelab.FriendlyChatSwift".
  3. Masukkan ID App Store sebagai "123456".
  4. Klik Daftarkan Aplikasi.

Tambahkan file GoogleService-Info.plist ke aplikasi Anda

Di layar kedua, klik Download GoogleService-Info.plist untuk mendownload file konfigurasi yang berisi semua metadata Firebase yang diperlukan untuk aplikasi Anda. Salin file tersebut ke aplikasi Anda dan tambahkan ke target FriendlyChatSwift.

Sekarang Anda dapat mengklik "x" di pojok kanan atas pop-up untuk menutupnya – melewati langkah 3 dan 4 – karena Anda akan melakukan langkah-langkah tersebut di sini.

19d59efb213ddbdc.png

Impor modul Firebase

Mulai dengan memastikan modul Firebase diimpor.

AppDelegate.swift, FCViewController.swift

import Firebase

Mengonfigurasi Firebase di AppDelegate

Gunakan metode "configure" di FirebaseApp dalam fungsi application:didFinishLaunchingWithOptions untuk mengonfigurasi layanan Firebase pokok dari file .plist Anda.

AppDelegate.swift

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

5. Mengidentifikasi Pengguna

Menggunakan Aturan Untuk Membatasi Akses ke Pengguna yang Diautentikasi

Sekarang kita akan menambahkan aturan untuk mewajibkan autentikasi sebelum membaca atau menulis pesan apa pun. Untuk melakukannya, kita menambahkan aturan berikut ke objek data pesan. Dari dalam bagian Database di Firebase console, pilih Realtime Database, lalu klik tab Rules. Kemudian, perbarui aturan agar terlihat seperti ini:

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

Untuk mengetahui informasi selengkapnya tentang cara kerjanya (termasuk dokumentasi tentang variabel "auth"), lihat dokumentasi keamanan Firebase.

Konfigurasi Authentication API

Sebelum aplikasi Anda dapat mengakses Firebase Authentication API atas nama pengguna, Anda harus mengaktifkannya

  1. Buka Firebase console dan pilih project Anda
  2. Pilih Autentikasi
  3. Pilih tab Metode Login
  4. Alihkan tombol Google ke aktif (biru)
  5. Tekan Simpan pada dialog yang muncul

Jika Anda mendapatkan error nanti di codelab ini dengan pesan "CONFIGURATION_NOT_FOUND", kembali ke langkah ini dan periksa kembali pekerjaan Anda.

Mengonfirmasi dependensi Firebase Auth

Pastikan dependensi Firebase Auth ada di file Podfile.

Podfile

pod 'Firebase/Auth'

Siapkan Info.plist untuk Login dengan Google.

Anda harus menambahkan skema URL kustom ke project XCode Anda.

  1. Buka konfigurasi project Anda: klik dua kali nama project dalam tampilan hierarki di sebelah kiri. Pilih aplikasi Anda dari bagian TARGET, lalu pilih tab Info, dan perluas bagian URL Types.
  2. Klik tombol +, lalu tambahkan skema URL untuk client ID terbalik Anda. Untuk menemukan nilai ini, buka file konfigurasi GoogleService-Info.plist, lalu cari kunci REVERSED_CLIENT_ID. Salin nilai kunci tersebut, lalu tempelkan ke kotak Skema URL di halaman konfigurasi. Biarkan kolom lainnya kosong.
  3. Jika sudah selesai, konfigurasi Anda akan terlihat seperti berikut (tetapi dengan nilai khusus aplikasi Anda):

1b54d5bd2f4f1448.png

Menetapkan clientID untuk Login dengan Google

Setelah Firebase dikonfigurasi, kita dapat menggunakan clientID untuk menyiapkan Login dengan Google di dalam metode "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
}

Tambahkan pengendali login

Setelah hasil Login dengan Google berhasil, gunakan akun untuk melakukan autentikasi dengan 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
      }
    }
  }

Membuat pengguna login secara otomatis. Kemudian, tambahkan pemroses ke Firebase Auth, untuk mengizinkan pengguna masuk ke aplikasi, setelah berhasil login. Hapus pemroses saat 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)
    }
  }

Logout

Tambahkan metode Logout

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

Menguji Membaca Pesan sebagai Pengguna yang Login

  1. Klik tombol 98205811bbed9d74.pngRun.
  2. Anda akan langsung diarahkan ke layar login. Ketuk tombol Login dengan Google.
  3. Kemudian, Anda akan diarahkan ke layar pesan jika semuanya berfungsi dengan baik.

6. Mengaktifkan Realtime Database

2efe6805ef369641.png

Mengimpor Pesan

Di project Anda di Firebase console, pilih item Database di menu navigasi sebelah kiri. Di menu tambahan Database, pilih Impor JSON. Jelajahi file initial_messages.json di direktori friendlychat, pilih, lalu klik tombol Import. Tindakan ini akan menggantikan semua data yang saat ini ada di database Anda. Anda juga dapat mengedit database secara langsung, menggunakan + hijau dan x merah untuk menambahkan dan menghapus item.

20ccf4856b715b4c.png

Setelah diimpor, database Anda akan terlihat seperti ini:

f3e0367f1c9cd187.png

Mengonfirmasi Ketergantungan Firebase Database

Di blok dependensi file Podfile, konfirmasi bahwa Firebase/Database disertakan.

Podfile

pod 'Firebase/Database'

Menyinkronkan Pesan yang Ada

Tambahkan kode yang menyinkronkan pesan yang baru ditambahkan ke UI aplikasi.

Kode yang Anda tambahkan di bagian ini akan:

  • Lakukan inisialisasi database Firebase dan tambahkan pemroses untuk menangani perubahan yang dilakukan pada database.
  • Perbarui DataSnapshot agar pesan baru ditampilkan.

Ubah metode "deinit", "configureDatabase", dan "tableView:cellForRow indexPath:" FCViewController; ganti dengan kode yang ditentukan di bawah:

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
  }

Uji Sinkronisasi Pesan

  1. Klik tombol 98205811bbed9d74.pngRun.
  2. Klik tombol Login untuk memulai guna membuka jendela pesan.
  3. Tambahkan pesan baru langsung di Firebase console dengan mengklik simbol + hijau di samping entri "messages" dan menambahkan objek seperti berikut: f9876ffc8b316b14.png
  4. Pastikan bahwa mereka muncul di UI Friendly-Chat.

7. Mengirim Pesan

Menerapkan Kirim Pesan

Mendorong nilai ke database. Saat Anda menggunakan metode push untuk menambahkan data ke Firebase Realtime Database, ID otomatis akan ditambahkan. ID yang dibuat otomatis ini berurutan, yang memastikan bahwa pesan baru akan ditambahkan dalam urutan yang benar.

Ubah metode "sendMessage:" FCViewController; ganti dengan kode yang ditentukan di bawah:

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

Menguji Pengiriman Pesan

  1. Klik tombol 98205811bbed9d74.pngRun.
  2. Klik Login untuk membuka jendela pesan.
  3. Ketik pesan, lalu tekan kirim. Pesan baru akan terlihat di UI aplikasi dan di Firebase console.

8. Menyimpan dan Menerima gambar

Konfirmasi Dependensi Firebase Storage

Di blok dependensi Podfile, konfirmasi bahwa Firebase/Storage disertakan.

Podfile

pod 'Firebase/Storage'

Menyiapkan Cloud Storage for Firebase

Berikut cara menyiapkan Cloud Storage for Firebase di project Firebase Anda:

  1. Di panel kiri Firebase console, luaskan Build, lalu pilih Storage.
  2. Klik Get started.
  3. Pilih lokasi untuk bucket Storage default Anda.
    Bucket di US-WEST1, US-CENTRAL1, dan US-EAST1 dapat memanfaatkan paket"Selalu Gratis" untuk Google Cloud Storage. Bucket di semua lokasi lainnya mengikuti harga dan penggunaan Google Cloud Storage.
  4. Klik Mulai dalam mode pengujian. Baca pernyataan penyangkalan tentang aturan keamanan.
    Di codelab ini, Anda akan menambahkan aturan keamanan untuk mengamankan data. Jangan mendistribusikan atau mengekspos aplikasi ke publik tanpa menambahkan Aturan Keamanan untuk bucket Storage Anda.
  5. Klik Buat.

Mengonfigurasi FirebaseStorage

FCViewController.swift

  func configureStorage() {
    storageRef = Storage.storage().reference()
  }

Menerima gambar dalam pesan yang ada

Tambahkan kode yang mendownload gambar dari Firebase Storage.

Ubah metode "tableView: cellForRowAt indexPath:" FCViewController; ganti dengan kode yang ditentukan di bawah:

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. Mengirim Pesan Gambar

Menerapkan Penyimpanan dan Pengiriman Gambar

Upload gambar dari pengguna, lalu sinkronkan URL penyimpanan gambar ini ke database sehingga gambar ini dikirim di dalam pesan.

Ubah metode "imagePickerController: didFinishPickingMediaWithInfo:" FCViewController Anda; ganti dengan kode yang ditentukan di bawah:

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

Menguji Pengiriman dan Penerimaan Pesan Gambar

  1. Klik tombol 98205811bbed9d74.pngRun.
  2. Klik Login untuk membuka jendela pesan.
  3. Klik ikon "tambahkan foto" untuk memilih foto. Pesan baru dengan foto akan terlihat di UI aplikasi dan di Firebase console.

10. Selamat!

Anda telah menggunakan Firebase untuk membuat aplikasi chat real-time dengan mudah.

Yang telah kita bahas

  • Realtime Database
  • Login Gabungan
  • Penyimpanan

Pelajari Lebih Lanjut