1. Ringkasan
Selamat datang di codelab Chat Ramah. Dalam codelab ini, Anda akan mempelajari cara menggunakan platform Firebase untuk membuat aplikasi iOS. Anda akan mengimplementasikan klien chat dan memantau performanya menggunakan Firebase.
Hal yang akan Anda pelajari
- Izinkan pengguna login.
- Menyinkronkan data menggunakan Firebase Realtime Database.
- Menyimpan file biner di Firebase Storage.
Hal yang akan Anda perlukan
- Xcode
- CocoaPods
- Perangkat pengujian dengan iOS 8.0+ atau simulator
Bagaimana Anda akan menggunakan tutorial ini?
Bagaimana penilaian Anda terhadap pengalaman membuat aplikasi iOS?
2. Mendapatkan kode contoh
Clone repositori GitHub dari command line.
$ git clone https://github.com/firebase/codelab-friendlychat-ios
3. Membangun aplikasi awal
Untuk membangun aplikasi awal:
- Di jendela terminal, buka direktori
ios-starter/swift-starter
dari download kode contoh Anda - Jalankan
pod install --repo-update
- Buka file FriendlyChatSwift.xcworkspace untuk membuka project di Xcode.
- Klik tombol Run.
Anda akan melihat layar utama Friendly Chat muncul setelah beberapa detik. UI akan muncul. Namun, untuk saat ini Anda tidak dapat login, mengirim, atau menerima pesan. Aplikasi akan dibatalkan dengan pengecualian hingga Anda menyelesaikan langkah berikutnya.
4. Membuat Project Firebase console
Buat project
Dari Firebase console, pilih Add Project.
Panggil project FriendlyChat
, lalu klik Create Project.
Menghubungkan aplikasi iOS
- Dari layar Ringkasan Project di project baru Anda, klik Tambahkan Firebase ke aplikasi iOS.
- Masukkan ID paket, sebagai "
com.google.firebase.codelab.FriendlyChatSwift
". - Masukkan ID App Store sebagai "
123456
". - Klik Daftarkan Aplikasi.
Menambahkan file GoogleService-Info.plist ke aplikasi Anda
Di layar kedua, klik Download GoogleService-Info.plist untuk mendownload file konfigurasi yang berisi semua metadata Firebase yang diperlukan untuk aplikasi Anda. Salin file tersebut ke aplikasi Anda dan tambahkan ke target FriendlyChatSwift.
Anda sekarang dapat mengeklik "x" di sudut kanan atas pop-up untuk menutupnya – melewati langkah 3 dan 4 – karena Anda akan melakukan langkah-langkah tersebut di sini.
Mengimpor modul Firebase
Mulai dengan memastikan modul Firebase
diimpor.
Tailwind.swift, FCViewController.swift
import Firebase
Mengonfigurasi Firebase di Tailwind
Menggunakan "konfigurasi" di FirebaseApp dalam fungsi application:didFinishLaunchingWithOptions untuk mengonfigurasi layanan Firebase yang mendasarinya dari file .plist Anda.
Podfile.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GIDSignIn.sharedInstance().delegate = self
return true
}
5. Identifikasi Pengguna
Gunakan Aturan Untuk Dibatasi pada Pengguna yang Diautentikasi
Sekarang kita akan menambahkan aturan untuk mewajibkan autentikasi sebelum membaca atau menulis pesan apa pun. Untuk melakukannya, tambahkan aturan berikut ke objek data pesan. Dari bagian Database di Firebase console, pilih Realtime Database, lalu klik tab Rules. Kemudian perbarui aturannya agar terlihat seperti ini:
{
"rules": {
"messages": {
".read": "auth != null",
".write": "auth != null"
}
}
}
Untuk informasi lebih lanjut tentang cara kerjanya (termasuk dokumentasi tentang variabel "auth") lihat dokumentasi keamanan Firebase.
Mengonfigurasi Authentication API
Sebelum aplikasi Anda dapat mengakses Firebase Authentication API atas nama pengguna, Anda harus mengaktifkannya
- Buka Firebase console dan pilih project Anda
- Pilih Autentikasi
- Pilih tab Metode Login
- Alihkan tombol Google ke aktif (biru)
- Tekan Simpan pada dialog yang muncul
Jika nanti Anda mendapatkan error dalam codelab ini dengan pesan "CONFIGURATION_NOT_FOUND", kembali ke langkah ini dan periksa kembali pekerjaan Anda.
Mengonfirmasi dependensi Firebase Auth
Pastikan dependensi Firebase Auth ada di file Podfile
.
Podfile
pod 'Firebase/Auth'
Siapkan Info.plist untuk Login dengan Google.
Anda harus menambahkan skema URL kustom ke project XCode.
- Buka konfigurasi project: klik dua kali pada nama project di tampilan hierarki sebelah kiri. Pilih aplikasi dari bagian TARGETS, lalu pilih tab Info, dan perluas bagian URL Types.
- Klik tombol +, lalu tambahkan skema URL untuk client ID terbalik Anda. Untuk menemukan nilai ini, buka file konfigurasi GoogleService-Info.plist, dan cari kunci REVERSED_CLIENT_ID. Salin nilai kunci tersebut, lalu tempelkan ke kotak Skema URL di halaman konfigurasi. Biarkan kolom lainnya kosong.
- Jika sudah selesai, konfigurasi akan terlihat seperti berikut (tapi dengan nilai khusus aplikasi Anda):
Menetapkan clientID untuk Login dengan Google
Setelah Firebase dikonfigurasi, kita dapat menggunakan clientID untuk menyiapkan Login dengan Google di dalam perintah "didFinishLaunchingWithOptions:" .
Podfile.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
}
Menambahkan pengendali login
Setelah hasil Login dengan Google berhasil, gunakan akun tersebut untuk melakukan autentikasi dengan Firebase.
Podfile.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
}
}
}
Memproses login pengguna secara otomatis. Kemudian tambahkan pemroses ke Firebase Auth, untuk mengizinkan pengguna masuk ke aplikasi, setelah berhasil login. Dan menghapus pemroses pada 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)
}
}
Logout
Menambahkan metode Logout
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)")
}
}
Menguji Membaca Pesan sebagai Pengguna yang Login
- Klik tombol Run.
- Anda akan segera diarahkan ke layar login. Ketuk tombol Login dengan Google.
- Anda akan diarahkan ke layar fitur pesan jika semuanya berfungsi dengan baik.
6. Mengaktifkan Realtime Database
Mengimpor Pesan
Di project Anda di Firebase console, pilih item Database di menu navigasi sebelah kiri. Di menu tambahan Database, pilih Import JSON. Cari file initial_messages.json
di direktori friendlychat, pilih file tersebut, lalu klik tombol Import. Tindakan ini akan menggantikan data apa pun yang saat ini ada dalam database Anda. Anda juga dapat mengedit {i>database<i} secara langsung, menggunakan tanda x hijau dan merah untuk menambahkan dan menghapus item.
Setelah mengimpor database Anda, akan terlihat seperti ini:
Mengonfirmasi Dependensi Firebase Database
Dalam blok dependensi file Podfile
, pastikan Firebase/Database
disertakan.
Podfile
pod 'Firebase/Database'
Menyinkronkan Pesan yang Ada
Menambahkan kode yang menyinkronkan pesan yang baru ditambahkan ke UI aplikasi.
Kode yang Anda tambahkan di bagian ini akan:
- Lakukan inisialisasi database Firebase dan tambahkan pemroses untuk menangani perubahan yang dibuat pada database.
- Update
DataSnapshot
agar pesan baru ditampilkan.
Ubah "deinit", "configureDatabase", dan "tableView:cellForRow indexPath:" FCViewController Anda metode; ganti dengan kode yang ditentukan di bawah ini:
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
}
Menguji Sinkronisasi Pesan
- Klik tombol Run.
- Klik tombol Login untuk memulai guna membuka jendela pesan.
- Tambahkan pesan baru langsung di Firebase console dengan mengklik simbol + berwarna hijau di sebelah "messages" entri dan penambahan objek seperti berikut:
- Pastikan mereka muncul di UI Friendly-Chat.
7. Mengirim Pesan
Menerapkan Kirim Pesan
Mendorong nilai ke database. Ketika Anda menggunakan metode push untuk menambahkan data ke Firebase Realtime Database, ID otomatis akan ditambahkan. ID yang dibuat otomatis ini berurutan, yang memastikan bahwa pesan baru akan ditambahkan dalam urutan yang benar.
Ubah "sendMessage:" FCViewController Anda metode; ganti dengan kode yang ditentukan di bawah ini:
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)
}
Menguji Pengiriman Pesan
- Klik tombol Run.
- Klik Login untuk membuka jendela pesan.
- Ketik pesan dan tekan kirim. Pesan baru akan terlihat di UI aplikasi dan di Firebase console.
8. Simpan dan Terima gambar
Mengonfirmasi Dependensi Firebase Storage
Dalam blok dependensi Podfile
, pastikan Firebase/Storage
disertakan.
Podfile
pod 'Firebase/Storage'
Aktifkan Firebase Storage di dasbor
Buka Firebase console dan pastikan Storage diaktifkan dengan "gs://PROJECTID.appspot.com" domain
Jika Anda melihat jendela aktivasi, klik "MULAI" untuk mengaktifkannya dengan aturan default.
Mengonfigurasi FirebaseStorage
FCViewController.swift
func configureStorage() {
storageRef = Storage.storage().reference()
}
Menerima gambar di pesan yang ada
Tambahkan kode yang mendownload gambar dari Firebase Storage.
Ubah "tableView: cellForRowAt indexPath:" FCViewController Anda metode; ganti dengan kode yang ditentukan di bawah ini:
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. Kirim Pesan Gambar
Menerapkan Simpan dan Kirim Gambar
Upload gambar dari pengguna, lalu sinkronkan URL penyimpanan gambar ini ke database sehingga gambar ini dikirimkan di dalam pesan.
Modifikasi "imagePickerController: didFinish ChooseingMediaWithInfo:" FCViewController Anda metode; ganti dengan kode yang ditentukan di bawah ini:
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])
}
}
}
Menguji Mengirim dan Menerima Pesan Gambar
- Klik tombol Run.
- Klik Login untuk membuka jendela pesan.
- Klik "tambahkan foto" ikon untuk memilih foto. Pesan baru dengan foto akan terlihat di UI aplikasi dan di Firebase console.
10. Selamat!
Anda telah menggunakan Firebase untuk membangun aplikasi chat real-time dengan mudah.
Yang telah kita bahas
- Realtime Database
- Login Gabungan
- Penyimpanan