1. Przegląd
Witamy w laboratorium kodowania przyjaznego czatu. W tym laboratorium kodowania dowiesz się, jak używać platformy Firebase do tworzenia aplikacji na iOS. Zaimplementujesz klienta czatu i będziesz monitorować jego działanie za pomocą Firebase.
To laboratorium kodów jest również dostępne w Objective-C.
Czego się nauczysz
- Zezwól użytkownikom na logowanie.
- Synchronizuj dane za pomocą bazy danych czasu rzeczywistego Firebase.
- Przechowuj pliki binarne w Firebase Storage.
Co będziesz potrzebował
- Xcode
- KakaoPods
- Urządzenie testowe z systemem iOS 8.0+ lub symulatorem
Jak będziesz korzystać z tego samouczka?
Jak oceniasz swoje doświadczenie w tworzeniu aplikacji na iOS?
2. Pobierz przykładowy kod
Sklonuj repozytorium GitHub z wiersza poleceń.
$ git clone https://github.com/firebase/codelab-friendlychat-ios
3. Zbuduj aplikację startową
Aby zbudować aplikację startową:
- W oknie terminala przejdź do
ios-starter/swift-starter
z przykładowego kodu do pobrania - Uruchom
pod install --repo-update
- Otwórz plik FriendlyChatSwift.xcworkspace, aby otworzyć projekt w Xcode.
- Kliknij
Przycisk Uruchom .
Po kilku sekundach powinieneś zobaczyć ekran główny przyjaznego czatu. Powinien pojawić się interfejs użytkownika. Jednak w tym momencie nie możesz się logować, wysyłać ani odbierać wiadomości. Aplikacja zostanie przerwana z wyjątkiem, dopóki nie wykonasz następnego kroku.
4. Utwórz projekt konsoli Firebase
Utwórz projekt
Z konsoli Firebase wybierz Dodaj projekt .
Wywołaj projekt FriendlyChat
, a następnie kliknij Utwórz projekt .
Połącz swoją aplikację na iOS
- Na ekranie Przegląd projektu nowego projektu kliknij Dodaj Firebase do swojej aplikacji na iOS .
- Wprowadź identyfikator pakietu w postaci „
com.google.firebase.codelab.FriendlyChatSwift
”. - Wprowadź identyfikator App Store jako „
123456
”. - Kliknij Zarejestruj aplikację .
Dodaj plik GoogleService-Info.plist do swojej aplikacji
Na drugim ekranie kliknij Pobierz GoogleService-Info.plist , aby pobrać plik konfiguracyjny zawierający wszystkie niezbędne metadane Firebase dla Twojej aplikacji. Skopiuj ten plik do swojej aplikacji i dodaj go do celu FriendlyChatSwift .
Możesz teraz kliknąć „x” w prawym górnym rogu wyskakującego okienka, aby je zamknąć – pomijając kroki 3 i 4 – ponieważ wykonasz te kroki tutaj.
Importuj moduł Firebase
Zacznij od upewnienia się, że moduł Firebase
został zaimportowany.
AppDelegate.swift , FCViewController.swift
import Firebase
Skonfiguruj Firebase w AppDelegate
Użyj metody „configure” w FirebaseApp wewnątrz funkcji application:didFinishLaunchingWithOptions, aby skonfigurować podstawowe usługi Firebase z pliku .plist.
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GIDSignIn.sharedInstance().delegate = self
return true
}
5. Zidentyfikuj użytkowników
Użyj reguł, aby ograniczyć dostęp do uwierzytelnionych użytkowników
Dodamy teraz regułę wymagającą uwierzytelnienia przed odczytaniem lub zapisaniem jakichkolwiek wiadomości. W tym celu dodajemy następujące reguły do naszego obiektu danych wiadomości. W sekcji Baza danych konsoli Firebase wybierz Bazę danych czasu rzeczywistego, a następnie kliknij kartę Reguły. Następnie zaktualizuj reguły, aby wyglądały tak:
{
"rules": {
"messages": {
".read": "auth != null",
".write": "auth != null"
}
}
}
Aby uzyskać więcej informacji o tym, jak to działa (w tym dokumentację dotyczącą zmiennej „auth”), zobacz dokumentację zabezpieczeń Firebase .
Skonfiguruj interfejsy API uwierzytelniania
Zanim aplikacja będzie mogła uzyskać dostęp do interfejsów Firebase Authentication API w imieniu użytkowników, musisz ją włączyć
- Przejdź do konsoli Firebase i wybierz swój projekt
- Wybierz Uwierzytelnianie
- Wybierz kartę Metoda logowania
- Przełącz przełącznik Google na włączony (niebieski)
- Naciśnij Zapisz w wyświetlonym oknie dialogowym
Jeśli później w tym laboratorium kodów pojawią się błędy z komunikatem „CONFIGURATION_NOT_FOUND”, wróć do tego kroku i ponownie sprawdź swoją pracę.
Potwierdź zależność Firebase Auth
Potwierdź, że w pliku Podfile
istnieją zależności Firebase Auth.
Podplik
pod 'Firebase/Auth'
Skonfiguruj plik Info.plist do logowania przez Google.
Musisz dodać niestandardowy schemat adresu URL do swojego projektu XCode.
- Otwórz konfigurację projektu: kliknij dwukrotnie nazwę projektu w lewym widoku drzewa. Wybierz swoją aplikację z sekcji CELE, następnie wybierz kartę Informacje i rozwiń sekcję Typy adresów URL.
- Kliknij przycisk + i dodaj schemat adresu URL dla odwróconego identyfikatora klienta. Aby znaleźć tę wartość, otwórz plik konfiguracyjny GoogleService-Info.plist i poszukaj klucza REVERSED_CLIENT_ID. Skopiuj wartość tego klucza i wklej ją w polu Schematy adresów URL na stronie konfiguracji. Pozostałe pola pozostaw puste.
- Po zakończeniu konfiguracja powinna wyglądać podobnie do poniższej (ale z wartościami specyficznymi dla aplikacji):
Ustaw identyfikator klienta dla logowania Google
Po skonfigurowaniu Firebase możemy użyć identyfikatora klienta do skonfigurowania logowania Google w metodzie „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
}
Dodaj moduł obsługi logowania
Gdy logowanie Google zakończy się pomyślnie, użyj konta do uwierzytelnienia w 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
}
}
}
Automatycznie zaloguj użytkownika. Następnie dodaj słuchacza do Firebase Auth, aby umożliwić użytkownikowi dostęp do aplikacji po pomyślnym zalogowaniu. I usuń słuchacza na 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)
}
}
Wyloguj się
Dodaj metodę wylogowania
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)")
}
}
Przetestuj czytanie wiadomości jako zalogowany użytkownik
- Kliknij
Przycisk Uruchom .
- Powinieneś natychmiast przejść do ekranu logowania. Stuknij przycisk logowania Google.
- Powinieneś zostać wysłany do ekranu wiadomości, jeśli wszystko działało dobrze.
6. Aktywuj bazę danych czasu rzeczywistego
Importuj wiadomości
W swoim projekcie w konsoli Firebase wybierz element Baza danych na lewym pasku nawigacyjnym. W rozszerzonym menu Bazy danych wybierz opcję Importuj JSON . Przejdź do pliku initial_messages.json
w katalogu friendlychat, zaznacz go, a następnie kliknij przycisk Importuj . Spowoduje to zastąpienie wszelkich danych znajdujących się obecnie w bazie danych. Możesz także edytować bazę danych bezpośrednio, używając zielonego + i czerwonego x, aby dodawać i usuwać elementy.
Po zaimportowaniu baza danych powinna wyglądać tak:
Potwierdź zależność bazy danych Firebase
W bloku zależności pliku Podfile
potwierdź, że uwzględniono Firebase/Database
.
Podplik
pod 'Firebase/Database'
Synchronizuj istniejące wiadomości
Dodaj kod, który synchronizuje nowo dodane wiadomości z interfejsem aplikacji.
Kod dodany w tej sekcji:
- Zainicjuj bazę danych Firebase i dodaj detektor do obsługi zmian wprowadzonych w bazie danych.
- Zaktualizuj
DataSnapshot
, aby wyświetlały się nowe wiadomości.
Zmodyfikuj metody „deinit”, „configureDatabase” i „tableView:cellForRow indexPath:” kontrolera FCViewController; zastąpić kodem zdefiniowanym poniżej:
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
}
Przetestuj synchronizację wiadomości
- Kliknij
Przycisk Uruchom .
- Kliknij przycisk Zaloguj się, aby rozpocząć, aby przejść do okna wiadomości.
- Dodaj nowe wiadomości bezpośrednio w konsoli Firebase, klikając zielony symbol + obok wpisu „wiadomości” i dodając obiekt podobny do następującego:
- Potwierdź, że pojawiają się w interfejsie przyjaznego czatu.
7. Wysyłaj wiadomości
Zaimplementuj Wyślij wiadomość
Wypchnij wartości do bazy danych. Gdy użyjesz metody push do dodania danych do Bazy danych czasu rzeczywistego Firebase, zostanie dodany automatyczny identyfikator. Te automatycznie generowane identyfikatory są sekwencyjne, co gwarantuje, że nowe wiadomości będą dodawane we właściwej kolejności.
Zmodyfikuj metodę „sendMessage:” kontrolera FCViewController; zastąpić kodem zdefiniowanym poniżej:
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)
}
Testowanie wysyłania wiadomości
- Kliknij
Przycisk Uruchom .
- Kliknij Zaloguj się, aby przejść do okna wiadomości.
- Wpisz wiadomość i naciśnij wyślij. Nowa wiadomość powinna być widoczna w interfejsie aplikacji i konsoli Firebase.
8. Przechowuj i odbieraj obrazy
Potwierdź zależność pamięci masowej Firebase
W bloku zależności pliku Podfile
potwierdź, że dołączono Firebase/Storage
.
Podplik
pod 'Firebase/Storage'
Aktywuj Firebase Storage na pulpicie nawigacyjnym
Przejdź do konsoli Firebase i potwierdź, że Storage jest aktywowany z domeną „gs://PROJECTID.appspot.com”.
Jeśli zamiast tego widzisz okno aktywacji, kliknij „ROZPOCZNIJ”, aby aktywować je z domyślnymi regułami.
Skonfiguruj FirebaseStorage
FCViewController.swift
func configureStorage() {
storageRef = Storage.storage().reference()
}
Odbieraj obrazy w istniejących wiadomościach
Dodaj kod, który pobiera obrazy z Firebase Storage.
Zmodyfikuj metodę „tableView: cellForRowAt indexPath:” kontrolera FCViewController; zastąpić kodem zdefiniowanym poniżej:
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. Wysyłaj wiadomości obrazkowe
Zaimplementuj przechowywanie i wysyłanie obrazów
Prześlij obraz od użytkownika, a następnie zsynchronizuj adres URL przechowywania tego obrazu z bazą danych, aby ten obraz został wysłany w wiadomości.
Zmodyfikuj metodę „imagePickerController: didFinishPickingMediaWithInfo:” kontrolera FCViewController; zastąpić kodem zdefiniowanym poniżej:
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])
}
}
}
Testuj wysyłanie i odbieranie wiadomości graficznych
- Kliknij
Przycisk Uruchom .
- Kliknij Zaloguj się, aby przejść do okna wiadomości.
- Kliknij ikonę „dodaj zdjęcie”, aby wybrać zdjęcie. Nowa wiadomość ze zdjęciem powinna być widoczna w interfejsie aplikacji oraz w konsoli Firebase.
10. Gratulacje!
Użyłeś Firebase do łatwego zbudowania aplikacji do czatu w czasie rzeczywistym.
Co omówiliśmy
- Baza danych czasu rzeczywistego
- Logowanie federacyjne
- Składowanie