Firebase iOS Codelab Swift

1. Обзор

2efe6805ef369641.png

Добро пожаловать в лабораторию «Дружественный чат». В этой кодовой лаборатории вы узнаете, как использовать платформу Firebase для создания приложений iOS. Вы реализуете чат-клиент и будете отслеживать его производительность с помощью Firebase.

Эта кодовая лаборатория также доступна в Objective-C.

Что ты узнаешь

  • Разрешить пользователям входить в систему.
  • Синхронизируйте данные с помощью базы данных 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. Run pod install --repo-update
  3. Откройте файл FriendlyChatSwift.xcworkspace, чтобы открыть проект в Xcode.
  4. Щелкните значок 98205811bbed9d74.png Выполнить кнопку.

Через несколько секунд вы должны увидеть главный экран Friendly Chat. Должен появиться пользовательский интерфейс. Однако на этом этапе вы не можете входить в систему, отправлять или получать сообщения. Приложение будет прервано с исключением, пока вы не выполните следующий шаг.

4. Создайте проект консоли Firebase.

Создать проект

С Firebase консоли выберите Добавить проект.

Вызов проекта FriendlyChat , а затем нажмите Создать проект.

Скриншот от 06.11.2015, 14: 13: 39.png

Подключите свое приложение для iOS

  1. На экране Обзор проекта вашего нового проекта, нажмите кнопку Добавить Firebase в приложение IOS.
  2. Введите расслоение ID, как « 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

Используйте метод «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. Определите пользователей

Используйте правила для ограничения только аутентифицированными пользователями

Теперь мы добавим правило, требующее аутентификации перед чтением или записью каких-либо сообщений. Для этого мы добавляем следующие правила к нашему объекту данных сообщений. Изнутри разделе База данных по Firebase консоли выберите в реальном времени базы данных, а затем нажмите на вкладку Правила. Затем обновите правила, чтобы они выглядели так:

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

Для получения более подробной информации о том , как это работает (включая документацию по переменному «Иденту») см Firebase документации по безопасности .

Настроить API аутентификации

Прежде чем ваше приложение сможет получить доступ к API аутентификации Firebase от имени ваших пользователей, вам необходимо включить его.

  1. Перейдите к Firebase консоли и выберите проект
  2. Выберите Authentication
  3. Выберите вкладку В знаковом методе
  4. Переключите переключатель Google к включенным (синий)
  5. Нажмите Сохранить на появившемся диалоговом окне

Если вы позже получите ошибки в этой кодовой таблице с сообщением «CONFIGURATION_NOT_FOUND», вернитесь к этому шагу и дважды проверьте свою работу.

Подтвердите зависимость Firebase Auth

Подтверждение Firebase аутентификации зависимости существуют в Podfile файле.

Подфайл

pod 'Firebase/Auth'

Настройте свой Info.plist для входа в Google.

Вам нужно будет добавить настраиваемую схему URL-адресов в свой проект XCode.

  1. Откройте конфигурацию проекта: дважды щелкните имя проекта в левом древовидном представлении. Выберите свое приложение в разделе ЦЕЛИ, затем выберите вкладку «Информация» и разверните раздел «Типы URL-адресов».
  2. Нажмите кнопку + и добавьте схему URL-адреса для обратного идентификатора клиента. Чтобы найти это значение, откройте файл конфигурации GoogleService-Info.plist и найдите ключ REVERSED_CLIENT_ID. Скопируйте значение этого ключа и вставьте его в поле Схемы URL-адресов на странице конфигурации. Остальные поля оставьте пустыми.
  3. По завершении ваша конфигурация должна выглядеть примерно так (но со значениями, зависящими от вашего приложения):

1b54d5bd2f4f1448.png

Установить 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 Auth, чтобы позволить пользователю войти в приложение после успешного входа в систему. И удалите слушателя при деинициализации.

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. Затем вы должны быть отправлены на экран обмена сообщениями, если все работает хорошо.

6. Активируйте базу данных в реальном времени.

2efe6805ef369641.png

Импортировать сообщения

В вашем проекте в Firebase консоли выберите пункт базы данных на левой навигационной панели. В меню переполнения базы данных выберите Импорт JSON. Перейдите к initial_messages.json файл в friendlychat каталоге, выберите его и нажмите кнопку Импорт. Это заменит все данные в вашей базе данных. Вы также можете редактировать базу данных напрямую, используя зеленый + и красный 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, щелкнув зеленый символ + рядом с записью «messages» и добавив объект, подобный следующему: f9876ffc8b316b14.png
  4. Убедитесь, что они отображаются в интерфейсе дружественного чата.

7. Отправляйте сообщения.

Реализовать отправку сообщения

Перенести значения в базу данных. Когда вы используете метод push для добавления данных в базу данных 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 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
  }

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, чтобы легко создать приложение для чата в реальном времени.

Что мы покрыли

  • База данных в реальном времени
  • Федеративный вход
  • Место хранения

Учить больше