1. Khái quát chung
Chào mừng bạn đến với phòng thí nghiệm mã hóa Trò chuyện thân thiện. Trong phòng thí nghiệm lập trình này, bạn sẽ tìm hiểu cách sử dụng nền tảng Firebase để tạo các ứng dụng iOS. Bạn sẽ triển khai ứng dụng trò chuyện và theo dõi hiệu suất của ứng dụng đó bằng Firebase.
Codelab này cũng có sẵn trong Objective-C.
Bạn sẽ học được gì
- Cho phép người dùng đăng nhập.
- Đồng bộ hóa dữ liệu bằng Cơ sở dữ liệu thời gian thực Firebase.
- Lưu trữ tệp nhị phân trong Bộ lưu trữ Firebase.
Những gì bạn cần
- Xcode
- Vỏ ca cao
- Thiết bị thử nghiệm chạy iOS 8.0 trở lên hoặc trình mô phỏng
Làm thế nào bạn sẽ sử dụng hướng dẫn này?
Làm thế nào để đánh giá kinh nghiệm của bạn với việc xây dựng các ứng dụng iOS?
2. Lấy mã mẫu
Sao chép kho lưu trữ GitHub từ dòng lệnh.
$ git clone https://github.com/firebase/codelab-friendlychat-ios
3. Xây dựng ứng dụng khởi động
Để xây dựng ứng dụng khởi động:
- Trong một cửa sổ đầu cuối, điều hướng đến
thư mục
ios-starter/swift-starter
từ tải xuống mã mẫu của bạn - Chạy
pod install --repo-update
- Mở tệp FriendlyChatSwift.xcworkspace để mở dự án trong Xcode.
- Nhấn vào
nút chạy .
Bạn sẽ thấy màn hình chính Trò chuyện thân thiện xuất hiện sau vài giây. Giao diện người dùng sẽ xuất hiện. Tuy nhiên, tại thời điểm này, bạn không thể đăng nhập, gửi hoặc nhận tin nhắn. Ứng dụng sẽ hủy bỏ với một ngoại lệ cho đến khi bạn hoàn thành bước tiếp theo.
4. Tạo Dự án bảng điều khiển Firebase
Tạo dự án
Từ bảng điều khiển Firebase, chọn Thêm dự án .
Gọi dự án FriendlyChat
, sau đó nhấp vào Tạo dự án .
Kết nối ứng dụng iOS của bạn
- Từ màn hình Tổng quan về dự án của dự án mới, hãy nhấp vào Thêm Firebase vào ứng dụng iOS của bạn .
- Nhập ID gói, dưới dạng "
com.google.firebase.codelab.FriendlyChatSwift
". - Nhập id App Store là "
123456
". - Nhấp vào Đăng ký ứng dụng .
Thêm tệp GoogleService-Info.plist vào ứng dụng của bạn
Trên màn hình thứ hai, hãy nhấp vào Tải xuống GoogleService-Info.plist để tải xuống tệp cấu hình chứa tất cả siêu dữ liệu Firebase cần thiết cho ứng dụng của bạn. Sao chép tệp đó vào ứng dụng của bạn và thêm nó vào mục tiêu FriendlyChatSwift .
Giờ đây, bạn có thể nhấp vào "x" ở góc trên bên phải của cửa sổ bật lên để đóng cửa sổ bật lên – bỏ qua bước 3 và 4 – vì bạn sẽ thực hiện các bước đó tại đây.
Nhập mô-đun Firebase
Bắt đầu bằng cách đảm bảo mô-đun Firebase
được nhập.
AppDelegate.swift , FCViewController.swift
import Firebase
Định cấu hình Firebase trong AppDelegate
Sử dụng phương pháp "đặt cấu hình" trong FirebaseApp bên trong hàm application:didFinishLaunchingWithOptions để định cấu hình các dịch vụ Firebase cơ bản từ tệp .plist của bạn.
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GIDSignIn.sharedInstance().delegate = self
return true
}
5. Xác định người dùng
Sử dụng các quy tắc để hạn chế người dùng được xác thực
Bây giờ chúng tôi sẽ thêm một quy tắc để yêu cầu xác thực trước khi đọc hoặc viết bất kỳ tin nhắn nào. Để làm điều này, chúng tôi thêm các quy tắc sau vào đối tượng dữ liệu thông báo của chúng tôi. Từ trong phần Cơ sở dữ liệu của bảng điều khiển Firebase , chọn Cơ sở dữ liệu thời gian thực, sau đó nhấp vào tab Quy tắc. Sau đó, cập nhật các quy tắc để chúng trông như thế này:
{
"rules": {
"messages": {
".read": "auth != null",
".write": "auth != null"
}
}
}
Để biết thêm thông tin về cách thức hoạt động của tính năng này (bao gồm cả tài liệu về biến "auth") hãy xem tài liệu bảo mật Firebase .
Định cấu hình API xác thực
Trước khi ứng dụng của bạn có thể thay mặt người dùng truy cập API xác thực Firebase, bạn sẽ phải kích hoạt nó
- Điều hướng đến bảng điều khiển Firebase và chọn dự án của bạn
- Chọn xác thực
- Chọn tab Phương thức đăng nhập
- Chuyển công tắc Google sang bật (màu xanh)
- Nhấn Save trên hộp thoại kết quả
Nếu sau này bạn gặp lỗi trong phòng thí nghiệm lập trình này với thông báo "CONFIGURATION_NOT_FOUND", hãy quay lại bước này và kiểm tra lại công việc của bạn.
Xác nhận phụ thuộc Firebase Auth
Xác nhận các phụ thuộc Firebase Auth tồn tại trong tệp Podfile
.
Podfile
pod 'Firebase/Auth'
Thiết lập Info.plist của bạn để Đăng nhập bằng Google.
Bạn sẽ cần thêm lược đồ URL tùy chỉnh vào dự án XCode của mình.
- Mở cấu hình dự án của bạn: nhấp đúp vào tên dự án ở chế độ xem dạng cây bên trái. Chọn ứng dụng của bạn từ phần MỤC TIÊU, sau đó chọn tab Thông tin và mở rộng phần Loại URL.
- Nhấp vào nút + và thêm lược đồ URL cho ID ứng dụng khách bị đảo ngược của bạn. Để tìm giá trị này, hãy mở tệp cấu hình GoogleService-Info.plist và tìm khóa REVERSED_CLIENT_ID. Sao chép giá trị của khóa đó và dán vào hộp Lược đồ URL trên trang cấu hình. Để trống các trường khác.
- Khi hoàn tất, cấu hình của bạn sẽ trông giống như sau (nhưng với các giá trị dành riêng cho ứng dụng của bạn):
Đặt clientID cho Đăng nhập bằng Google
Sau khi định cấu hình Firebase, chúng tôi có thể sử dụng clientID để thiết lập Đăng nhập bằng Google bên trong phương thức "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
}
Thêm trình xử lý đăng nhập
Sau khi có kết quả Đăng nhập bằng Google thành công, hãy sử dụng tài khoản để xác thực với 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
}
}
}
Tự động đăng nhập người dùng. Sau đó, thêm trình nghe vào Firebase Auth để cho phép người dùng vào ứng dụng sau khi đăng nhập thành công. Và xóa trình nghe trên 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)
}
}
Đăng xuất
Thêm phương thức Đăng xuất
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)")
}
}
Kiểm tra đọc tin nhắn với tư cách là người dùng đã đăng nhập
- Nhấn vào
nút chạy .
- Bạn sẽ được gửi ngay đến màn hình đăng nhập. Nhấn vào nút Đăng nhập Google.
- Sau đó, bạn sẽ được chuyển đến màn hình nhắn tin nếu mọi thứ hoạt động tốt.
6. Kích hoạt cơ sở dữ liệu thời gian thực
Nhập tin nhắn
Trong dự án của bạn trong bảng điều khiển Firebase, hãy chọn mục Cơ sở dữ liệu trên thanh điều hướng bên trái. Trong menu mục bổ sung của Cơ sở dữ liệu, chọn Nhập JSON . Duyệt đến tệp initial_messages.json
trong thư mục friendlychat, chọn tệp rồi nhấp vào nút Nhập . Thao tác này sẽ thay thế mọi dữ liệu hiện có trong cơ sở dữ liệu của bạn. Bạn cũng có thể chỉnh sửa trực tiếp cơ sở dữ liệu bằng cách sử dụng dấu x màu lục + và đỏ để thêm và xóa các mục.
Sau khi nhập cơ sở dữ liệu của bạn sẽ trông như thế này:
Xác nhận phụ thuộc cơ sở dữ liệu Firebase
Trong khối phụ thuộc của tệp Podfile
, hãy xác nhận rằng Firebase/Database
được bao gồm.
Podfile
pod 'Firebase/Database'
Đồng bộ hóa tin nhắn hiện có
Thêm mã đồng bộ hóa các tin nhắn mới được thêm vào giao diện người dùng ứng dụng.
Mã bạn thêm vào phần này sẽ:
- Khởi tạo cơ sở dữ liệu Firebase và thêm trình nghe để xử lý các thay đổi được thực hiện đối với cơ sở dữ liệu.
- Cập nhật
DataSnapshot
để hiển thị các thông báo mới.
Sửa đổi các phương thức "deinit", "configureDatabase" và "tableView:cellForRow indexPath:" của FCViewController của bạn; thay thế bằng mã được xác định bên dưới:
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
}
Kiểm tra đồng bộ hóa tin nhắn
- Nhấn vào
nút chạy .
- Nhấp vào nút Đăng nhập để bắt đầu để chuyển đến cửa sổ thư.
- Thêm tin nhắn mới trực tiếp trong bảng điều khiển Firebase bằng cách nhấp vào biểu tượng + màu xanh lá cây bên cạnh mục "tin nhắn" và thêm một đối tượng như sau:
- Xác nhận rằng chúng hiển thị trong Giao diện người dùng trò chuyện thân thiện.
7. Gửi tin nhắn
Triển khai Gửi tin nhắn
Đẩy các giá trị vào cơ sở dữ liệu. Khi bạn sử dụng phương thức đẩy để thêm dữ liệu vào Cơ sở dữ liệu thời gian thực của Firebase, một ID tự động sẽ được thêm vào. Các ID được tạo tự động này là tuần tự, đảm bảo rằng các thư mới sẽ được thêm vào theo đúng thứ tự.
Sửa đổi phương thức "sendMessage:" của FCViewController của bạn; thay thế bằng mã được xác định bên dưới:
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)
}
Kiểm tra gửi tin nhắn
- Nhấn vào
nút chạy .
- Nhấp vào Đăng nhập để chuyển đến cửa sổ tin nhắn.
- Nhập một tin nhắn và nhấn gửi. Thông báo mới sẽ hiển thị trong giao diện người dùng ứng dụng và trong bảng điều khiển Firebase.
8. Lưu trữ và nhận ảnh
Xác nhận phụ thuộc vào bộ nhớ Firebase
Trong khối phụ thuộc của Podfile
, hãy xác nhận bao gồm Firebase/Storage
.
Podfile
pod 'Firebase/Storage'
Kích hoạt Bộ lưu trữ Firebase trong bảng điều khiển
Truy cập bảng điều khiển Firebase và xác nhận rằng Bộ nhớ được kích hoạt với miền "gs://PROJECTID.appspot.com"
Thay vào đó, nếu bạn nhìn thấy cửa sổ kích hoạt, hãy nhấp vào "BẮT ĐẦU" để kích hoạt nó với các quy tắc mặc định.
Định cấu hình FirebaseStorage
FCViewController.swift
func configureStorage() {
storageRef = Storage.storage().reference()
}
Nhận hình ảnh trong tin nhắn hiện có
Thêm mã tải xuống hình ảnh từ Firebase Storage.
Sửa đổi phương thức "tableView: cellForRowAt indexPath:" của FCViewController của bạn; thay thế bằng mã được xác định bên dưới:
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. Gửi tin nhắn hình ảnh
Thực hiện lưu trữ và gửi hình ảnh
Tải lên một hình ảnh từ người dùng, sau đó đồng bộ hóa URL lưu trữ của hình ảnh này với cơ sở dữ liệu để hình ảnh này được gửi bên trong tin nhắn.
Sửa đổi phương thức "imagePickerController: didFinishPickingMediaWithInfo:" của FCViewController của bạn; thay thế bằng mã được xác định bên dưới:
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])
}
}
}
Kiểm tra gửi và nhận tin nhắn hình ảnh
- Nhấn vào
nút chạy .
- Nhấp vào Đăng nhập để chuyển đến cửa sổ tin nhắn.
- Nhấp vào biểu tượng "thêm ảnh" để chọn ảnh. Thông báo mới có ảnh sẽ hiển thị trong giao diện người dùng ứng dụng và trong bảng điều khiển Firebase.
10. Xin chúc mừng!
Bạn đã sử dụng Firebase để dễ dàng xây dựng ứng dụng trò chuyện thời gian thực.
Những gì chúng tôi đã bảo hiểm
- Cơ sở dữ liệu thời gian thực
- Đăng nhập liên kết
- Kho