Firebase iOS Codelab Swift

Firebase iOS Codelab Swift

О практической работе

subjectПоследнее обновление: нояб. 8, 2023
account_circleАвтор: сотрудник Google

1. Обзор

2efe6805ef369641.png

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

Что вы узнаете

  • Разрешите пользователям входить в систему.
  • Синхронизируйте данные с помощью базы данных Firebase Realtime.
  • Храните двоичные файлы в хранилище Firebase.

Что вам понадобится

  • 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 , затем нажмите Create Project .

Скриншот от 06.11.2015 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

Используйте метод «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"
   
}
 
}
}

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

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

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

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

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

Подтвердите зависимость аутентификации Firebase

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

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

2efe6805ef369641.png

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

В вашем проекте в консоли Firebase выберите элемент «База данных» на левой панели навигации. В дополнительном меню базы данных выберите «Импортировать 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. Отправлять сообщения

Внедрить отправку сообщения

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

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

Что мы рассмотрели

  • База данных реального времени
  • Федеративный вход
  • Хранилище

Узнать больше