Google is committed to advancing racial equity for Black communities. See how.
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

Firebase iOS Codelab Swift

2efe6805ef369641.png

歡迎使用友好聊天代碼實驗室。在此代碼實驗室中,您將學習如何使用Firebase平台創建iOS應用程序。您將實現一個聊天客戶端並使用Firebase監視其性能。

該代碼實驗室在Objective-C中也可用。

你會學到什麼

  • 允許用戶登錄。
  • 使用Firebase實時數據庫同步數據。
  • 將二進製文件存儲在Firebase存儲中。

你需要什麼

  • Xcode
  • 可可豆
  • 具有iOS 8.0+或模擬器的測試設備

您將如何使用本教程?

僅閱讀閱讀並完成練習

您如何評價構建iOS應用的體驗?

新手中間的精通

從命令行克隆GitHub存儲庫。

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

2f4c98d858c453fe.png

要構建入門應用程序:

  1. 在終端窗口中,導航到android_studio_folder.png樣本代碼下載中的ios-starter/swift-starter目錄
  2. 運行pod install --repo-update
  3. 打開FriendlyChatSwift.xcworkspace文件以Xcode打開項目。
  4. 點擊98205811bbed9d74.png運行按鈕。

幾秒鐘後,您應該會看到“友好聊天”主屏幕出現。 UI應該出現。但是,此時您無法登錄,發送或接收消息。該應用程序將異常終止,直到完成下一步。

建立專案

Firebase控制台中,選擇“添加項目”

將項目FriendlyChat ,然後單擊“創建項目”

2015年11月6日14:13:39.png的屏幕截圖

連接您的iOS應用

  1. 在新項目的“項目概述”屏幕中,點擊將Firebase添加到您的iOS應用
  2. 輸入捆綁軟件ID,例如“ com.google.firebase.codelab.FriendlyChatSwift ”。
  3. 輸入“ App Store ID”作為“ 123456 ”。
  4. 點擊註冊應用

將GoogleService-Info.plist文件添加到您的應用中

在第二個屏幕上,單擊Download GoogleService-Info.plist以下載一個配置文件,其中包含應用程序所有必需的Firebase元數據。將該文件複製到您的應用程序,並將其添加到FriendlyChatSwift目標。

現在,您可以單擊彈出窗口右上角的“ x”以將其關閉(跳過步驟3和4),因為您將在此處執行這些步驟。

19d59efb213ddbdc.png

導入Firebase模塊

首先確保已導入Firebase模塊。

AppDelegate.swiftFCViewController.swift

import Firebase

在AppDelegate中配置Firebase

在application:didFinishLaunchingWithOptions函數內的FirebaseApp中使用“配置”方法,以從.plist文件配置基礎Firebase服務。

AppDelegate.swift

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

使用規則限制通過身份驗證的用戶

現在,我們將添加一條規則,要求在讀取或寫入任何消息之前進行身份驗證。為此,我們向消息數據對象添加以下規則。從Firebase控制台的“數據庫”部分中,選擇“實時數據庫”,然後單擊“規則”選項卡。然後更新規則,使其如下所示:

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

有關此工作原理的更多信息(包括有關“ auth”變量的文檔),請參閱Firebase安全文檔

配置身份驗證API

在您的應用程序可以代表用戶訪問Firebase身份驗證API之前,您必須先啟用它

  1. 導航到Firebase控制台並選擇您的項目
  2. 選擇身份驗證
  3. 選擇登錄方法選項卡
  4. Google開關切換到啟用狀態(藍色)
  5. 在出現的對話框中按保存

如果稍後在此代碼實驗室中收到錯誤消息“ CONFIGURATION_NOT_FOUND”,請返回此步驟並仔細檢查您的工作。

確認Firebase Auth依賴性

確認Podfile文件中存在Firebase Auth依賴關係。

播客文件

pod 'Firebase/Auth'

為Google登錄設置您的Info.plist。

您需要向XCode項目中添加自定義URL方案。

  1. 打開項目配置:在左樹視圖中雙擊項目名稱。從“目標”部分中選擇您的應用,然後選擇“信息”選項卡,然後展開“ URL類型”部分。
  2. 單擊+按鈕,然後為您的反向客戶端ID添加URL方案。要找到此值,請打開GoogleService-Info.plist配置文件,然後查找REVERSED_CLIENT_ID密鑰。複製該鍵的值,然後將其粘貼到配置頁上的“ URL方案”框中。將其他字段留空。
  3. 完成後,您的配置應類似於以下內容(但具有特定於應用程序的值):

1b54d5bd2f4f1448.png

設置Google登錄的clientID

配置Firebase後,我們可以使用clientID在“ didFinishLaunchingWithOptions:”方法內設置Google登錄。

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. 您應該立即被發送到登錄屏幕。點擊Google登錄按鈕。
  3. 如果一切正常,則應將您發送到消息傳遞屏幕。

2efe6805ef369641.png

匯入訊息

Firebase控制台的項目中,選擇左側導航欄上的“數據庫”項。在數據庫的溢出菜單中,選擇導入JSON 。瀏覽到friendlychat目錄中的initial_messages.json文件,選擇它,然後單擊“導入”按鈕。這將替換數據庫中當前的所有數據。您也可以直接編輯數據庫,使用綠色+和紅色x添加和刪除項目。

20ccf4856b715b4c.png

導入數據庫後,應如下所示:

f3e0367f1c9cd187.png

確認Firebase數據庫依賴性

Podfile文件的依賴項塊中,確認其中包括Firebase/Database

播客文件

pod 'Firebase/Database'

同步現有消息

添加將新添加的消息同步到應用程序UI的代碼。

您在本節中添加的代碼將:

  • 初始化Firebase數據庫並添加偵聽器以處理對數據庫所做的更改。
  • 更新DataSnapshot以便顯示新消息。

修改FCViewController的“ deinit”,“ configureDatabase”和“ tableView:cellForRow indexPath:”方法;替換為下面定義的代碼:

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. 確認它們顯示在Friendly-Chat UI中。

實施發送消息

將值推送到數據庫。當您使用push方法將數據添加到Firebase Realtime數據庫時,將添加一個自動ID。這些自動生成的ID是順序的,這確保了將以正確的順序添加新消息。

修改您的FCViewController的“ sendMessage:”方法;替換為下面定義的代碼:

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控制台中可見。

確認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存儲下載圖像的代碼。

修改您的FCViewController的“ tableView:cellForRowAt indexPath:”方法;替換為下面定義的代碼:

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
  }

實施存儲和發送圖像

從用戶上載圖像,然後將該圖像的存儲URL同步到數據庫,以便將該圖像發送到消息中。

修改FCViewController的“ imagePickerController:didFinishPickingMediaWithInfo:”方法;替換為下面定義的代碼:

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控制台中可見。

您已使用Firebase輕鬆構建了實時聊天應用程序。

我們涵蓋的內容

  • 實時數據庫
  • 聯合登錄
  • 貯存

了解更多