Save the date - Google I/O returns May 18-20. Register to get the most out of the digital experience: Build your schedule, reserve space, participate in Q&As, earn Google Developer profile badges, and more. Register now
หน้านี้ได้รับการแปลโดย Cloud Translation API
Switch to English

Firebase iOS Codelab Swift

2efe6805ef369641.png

ยินดีต้อนรับสู่โค้ดแล็บแชทที่เป็นมิตร ใน codelab นี้คุณจะได้เรียนรู้วิธีใช้แพลตฟอร์ม Firebase เพื่อสร้างแอปพลิเคชัน iOS คุณจะติดตั้งโปรแกรมแชทและตรวจสอบประสิทธิภาพโดยใช้ Firebase

codelab นี้ยังมีอยู่ใน Objective-C

สิ่งที่คุณจะได้เรียนรู้

  • อนุญาตให้ผู้ใช้ลงชื่อเข้าใช้
  • ซิงค์ข้อมูลโดยใช้ฐานข้อมูลเรียลไทม์ของ Firebase
  • จัดเก็บไฟล์ไบนารีใน Firebase Storage

สิ่งที่คุณต้องการ

  • 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 ปุ่ม เรียกใช้

คุณควรเห็นหน้าจอหลักของ Friendly Chat ปรากฏขึ้นหลังจากผ่านไปสองสามวินาที UI ควรปรากฏขึ้น อย่างไรก็ตาม ณ จุดนี้คุณไม่สามารถลงชื่อเข้าใช้ส่งหรือรับข้อความได้ แอปจะยกเลิกโดยมีข้อยกเว้นจนกว่าคุณจะทำขั้นตอนถัดไป

สร้างโครงการ

จาก คอนโซล Firebase ให้เลือก เพิ่มโครงการ

โทรหาโครงการ FriendlyChat จากนั้นคลิกที่ สร้างโครงการ

สกรีนช็อตจาก 2015-11-06 14: 13: 39.png

เชื่อมต่อแอป iOS ของคุณ

  1. จากหน้าจอภาพรวมโครงการของโปรเจ็กต์ใหม่ของคุณให้คลิก เพิ่ม Firebase ในแอป iOS ของคุณ
  2. ป้อนรหัสบันเดิลเป็น " com.google.firebase.codelab.FriendlyChatSwift "
  3. ป้อนรหัส App Store เป็น " 123456 "
  4. คลิก ลงทะเบียนแอป

เพิ่มไฟล์ GoogleService-Info.plist ลงในแอปของคุณ

ในหน้าจอที่สองให้คลิก ดาวน์โหลด 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
}

ใช้กฎเพื่อ จำกัด เฉพาะผู้ใช้ที่พิสูจน์ตัวตน

ตอนนี้เราจะเพิ่มกฎเพื่อให้ต้องมีการตรวจสอบสิทธิ์ก่อนที่จะอ่านหรือเขียนข้อความใด ๆ ในการดำเนินการนี้เราจะเพิ่มกฎต่อไปนี้ในวัตถุข้อมูลข้อความของเรา จากในส่วนฐานข้อมูลของ คอนโซล Firebase ให้เลือกฐานข้อมูลเรียลไทม์จากนั้นคลิกแท็บกฎ จากนั้นอัปเดตกฎให้มีลักษณะดังนี้:

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

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงาน (รวมถึงเอกสารเกี่ยวกับตัวแปร "auth") โปรดดู เอกสารความปลอดภัยของ Firebase

กำหนดค่า API การตรวจสอบความถูกต้อง

ก่อนที่แอปพลิเคชันของคุณจะเข้าถึง Firebase Authentication API ในนามของผู้ใช้คุณจะต้องเปิดใช้งาน

  1. ไปที่ คอนโซล Firebase และเลือกโครงการของคุณ
  2. เลือกการ รับรองความถูกต้อง
  3. เลือกแท็บ วิธี การ ลงชื่อเข้าใช้
  4. สลับสวิตช์ Google เป็นเปิดใช้งาน (สีน้ำเงิน)
  5. กด บันทึก ในกล่องโต้ตอบผลลัพธ์

หากคุณพบข้อผิดพลาดในภายหลังใน codelab พร้อมข้อความ "CONFIGURATION_NOT_FOUND" ให้กลับมาที่ขั้นตอนนี้และตรวจสอบงาน

ยืนยันการพึ่งพา Firebase Auth

ยืนยันว่าการอ้างอิง Firebase Auth มีอยู่ในไฟล์ Podfile

Podfile

pod 'Firebase/Auth'

ตั้งค่า Info.plist ของคุณสำหรับ Google Sign In

คุณจะต้องเพิ่มรูปแบบ URL ที่กำหนดเองในโครงการ XCode ของคุณ

  1. เปิดการกำหนดค่าโครงการของคุณ: ดับเบิลคลิกที่ชื่อโครงการในมุมมองแบบต้นไม้ด้านซ้าย เลือกแอปของคุณจากส่วนเป้าหมายจากนั้นเลือกแท็บข้อมูลและขยายส่วนประเภท URL
  2. คลิกปุ่ม + และเพิ่มรูปแบบ URL สำหรับรหัสไคลเอ็นต์ที่กลับรายการของคุณ หากต้องการค้นหาค่านี้ให้เปิดไฟล์การกำหนดค่า GoogleService-Info.plist และมองหาคีย์ REVERSED_CLIENT_ID คัดลอกค่าของคีย์นั้นและวางลงในกล่อง URL Schemes ในหน้าการกำหนดค่า เว้นช่องอื่นว่างไว้
  3. เมื่อเสร็จสิ้นการกำหนดค่าของคุณควรมีลักษณะคล้ายกับสิ่งต่อไปนี้ (แต่มีค่าเฉพาะแอปพลิเคชันของคุณ):

1b54d5bd2f4f1448.png

ตั้งรหัสไคลเอ็นต์สำหรับ Google Sign In

หลังจากกำหนดค่า 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
      }
    }
  }

ลงชื่อเข้าใช้ผู้ใช้โดยอัตโนมัติ จากนั้นเพิ่ม Listener ใน Firebase Auth เพื่อให้ผู้ใช้เข้าสู่แอปได้หลังจากลงชื่อเข้าใช้สำเร็จและนำ Listener ออกเมื่อ 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 เรียกดูไฟล์ initial_messages.json ในไดเร็กทอรี friendlychat เลือกจากนั้นคลิกปุ่ม นำเข้า สิ่งนี้จะแทนที่ข้อมูลใด ๆ ที่อยู่ในฐานข้อมูลของคุณ คุณยังสามารถแก้ไขฐานข้อมูลได้โดยตรงโดยใช้เครื่องหมาย + สีเขียวและ x สีแดงเพื่อเพิ่มและลบรายการ

20ccf4856b715b4c.png

หลังจากนำเข้าฐานข้อมูลของคุณควรมีลักษณะดังนี้:

f3e0367f1c9cd187.png

ยืนยันการพึ่งพาฐานข้อมูล Firebase

ในบล็อกการอ้างอิงของไฟล์ Podfile ให้ยืนยันว่ามี Firebase/Database รวมอยู่ด้วย

Podfile

pod 'Firebase/Database'

ซิงโครไนซ์ข้อความที่มีอยู่

เพิ่มรหัสที่ซิงโครไนซ์ข้อความที่เพิ่งเพิ่มเข้ากับ UI ของแอป

รหัสที่คุณเพิ่มในส่วนนี้จะ:

  • เริ่มต้นฐานข้อมูล 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
  }

ทดสอบการซิงค์ข้อความ

  1. คลิก 98205811bbed9d74.png ปุ่ม เรียกใช้
  2. คลิกปุ่ม ลงชื่อเข้าใช้เพื่อเริ่มต้น เพื่อไปที่หน้าต่างข้อความ
  3. เพิ่มข้อความใหม่โดยตรงในคอนโซล Firebase โดยคลิกที่สัญลักษณ์ + สีเขียวถัดจากรายการ "ข้อความ" และเพิ่มวัตถุดังต่อไปนี้: f9876ffc8b316b14.png
  4. ยืนยันว่าปรากฏใน UI ที่เป็นมิตรกับแชท

ใช้การส่งข้อความ

ส่งค่าไปยังฐานข้อมูล เมื่อคุณใช้วิธีพุชเพื่อเพิ่มข้อมูลลงในฐานข้อมูลเรียลไทม์ของ 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)
  }

ทดสอบการส่งข้อความ

  1. คลิก 98205811bbed9d74.png ปุ่ม เรียกใช้
  2. คลิก ลงชื่อเข้า เพื่อไปที่หน้าต่างข้อความ
  3. พิมพ์ข้อความแล้วกดส่ง ข้อความใหม่ควรปรากฏใน UI ของแอปและในคอนโซล Firebase

ยืนยันการพึ่งพาที่เก็บข้อมูล Firebase

ในบล็อกการอ้างอิงของ Podfile ให้ยืนยันว่ารวม Firebase/Storage แล้ว

Podfile

pod 'Firebase/Storage'

เปิดใช้งาน Firebase Storage ในแดชบอร์ด

ไปที่คอนโซล 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
  }

ติดตั้ง Store และส่งภาพ

อัปโหลดภาพจากผู้ใช้จากนั้นซิงค์ 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. คลิกไอคอน "เพิ่มรูปภาพ" เพื่อเลือกรูปภาพ ข้อความใหม่พร้อมรูปภาพควรปรากฏใน UI ของแอปและในคอนโซล Firebase

คุณใช้ Firebase เพื่อสร้างแอปพลิเคชันแชทแบบเรียลไทม์ได้อย่างง่ายดาย

สิ่งที่เราได้กล่าวถึง

  • ฐานข้อมูลเรียลไทม์
  • ลงชื่อเข้าใช้แบบรวมศูนย์
  • การจัดเก็บ

เรียนรู้เพิ่มเติม