Trong phần phần trước (Sử dụng firebase với swift 3.x (phần 1)) tôi đã giới thiệu về tương tác với firebase thông qua connect và tạo phòng để có thể chat được. Phần này tôi xin được giới thiệu kỹ hơn về cách gửi message, image trong một ứng dụng realtime.

VII . Thiết lập Data Source và Delegate

Để hiển thị mesages, bạn cần một data source để cung cấp những đối tượng phù hợp cho JSQMessageData proto-col, và cần thực thi trong phương thức delegata. Bạn có thể tạo một class phù hợp với JSQMessageData
Ở đầu cùng của file ChatViewController, thêm thuộc tính sau

var messages = [JSQMessage]()

messages là một mảng lưu instances của JSQMessage
Bây giờ thêm đoạn code sau vào:

override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageDataForItemAt indexPath: IndexPath!) -> JSQMessageData! {
  return messages[indexPath.item]
}

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  return messages.count
}

Đoạn code đầu tiên ở trên giống collectionView(_:cellForItemAtIndexPath:), nhưng cho message data. Đoạn code thứ 2 ở trên là cách chuẩn để trả về số item trong mỗi section; trong trường hợp này, là số messages.

VIII . Message Bubble Colors

Những messagees được hiển thị trong collection view là những ảnh đơn giản. Có hai loại messages là outgoing và incoming. Outgoing messages được hiển thị bên phải và incoming messages được hiển thị bên trái.
Trong ChatViewController, thêm đoạn code sau vào UI và User Interaction:

private func setupOutgoingBubble() -> JSQMessagesBubbleImage {
  let bubbleImageFactory = JSQMessagesBubbleImageFactory()
  return bubbleImageFactory!.outgoingMessagesBubbleImage(with: UIColor.jsq_messageBubbleBlue())
}
  
private func setupIncomingBubble() -> JSQMessagesBubbleImage {
  let bubbleImageFactory = JSQMessagesBubbleImageFactory()
  return bubbleImageFactory!.incomingMessagesBubbleImage(with: UIColor.jsq_messageBubbleLightGray())
}

Sau đó thêm thuộc tính sau vào phần đầu:

lazy var outgoingBubbleImageView: JSQMessagesBubbleImage = self.setupOutgoingBubble()
lazy var incomingBubbleImageView: JSQMessagesBubbleImage = self.setupIncomingBubble()

JSQMessagesBubbleImageFactory là phương thức tạo các ảnh cho việc chat. Có một category được cung cấp bởi JSQMessagesViewController cái này có thể tạo được các message màu được dùng trong Messages app.
Dùng phương thức outgoingMessagesBubbleImage(:with)incomingMessagesBubbleImage(:with), bạn có thể tạo những ảnh cho outgoging và incoming messages.
Bạn sẽ cần thực thi phương thức delegate cho message.

IX . Thiết lập Bubble Images

Để thiết lập mầu ảnh cho mỗi message, bạn sẽ cần override một phương thức JSQMessagesCollectionViewDataSource được gọi collectionView(_:messageBubbleImageDataForItemAt:)
Thêm đoạn code sau vào ChatViewController:

override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAt indexPath: IndexPath!) -> JSQMessageBubbleImageDataSource! {
  let message = messages[indexPath.item] // 1
  if message.senderId == senderId { // 2
    return outgoingBubbleImageView
  } else { // 3
    return incomingBubbleImageView
  }
}

Đoạn code trên sẽ hoạt động như sau:

    1. Lấy message.
    1. Nếu message được gửi bởi mình thì trả về outgoing image
    1. Ngược lại trả về incoming image.

X . Xoá Avatars

JSQMessagesViewController cung cấp hỗ trợ cho avartars.
Thêm đoạn code dưới đây vào class ChatViewController

override func collectionView(_ collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAt indexPath: IndexPath!) -> JSQMessageAvatarImageDataSource! {
  return nil
}

Để xoá ảnh avatar đơn giản chỉ cần trả về nill cho mỗi avatar của messae hiển thị.
Cuối cùng, trong viewDidLoad() thêm đoạn sau vào

// No avatars
collectionView!.collectionViewLayout.incomingAvatarViewSize = CGSize.zero
collectionView!.collectionViewLayout.outgoingAvatarViewSize = CGSize.zero

Bây giờ show trên màn hình sẽ như sau

XI . Tạo Messages

Tạo phương thức sau trong ChatViewController:

private func addMessage(withId id: String, name: String, text: String) {
  if let message = JSQMessage(senderId: id, displayName: name, text: text) {
    messages.append(message)
  }
}

Phương thức này tạo một JSQMesssage mới và thêm vào data source.
Thêm một vài message để test vào trong viewDidAppear(_:) như sau:

// messages from someone else
addMessage(withId: "foo", name: "Mr.Bolt", text: "I am so fast!")
// messages sent from local sender
addMessage(withId: senderId, name: "Me", text: "I bet I can run faster than you!")
addMessage(withId: senderId, name: "Me", text: "I like to run!")
// animates the receiving of a new message on the view
finishReceivingMessage()

Build và chạy ứng dụng sẽ như sau:

Kết Luận

Các dự án hiện tại tôi đang tham gia đều sử dụng firebase của Google để phát triển các chức năng push notification, chat tôi thấy tốc độ và bảo mật khá tốt. Với tốc độ tiến hóa như hiện tại firebase sẽ dần dần dễ sử dụng và hoàn thiện hơn nếu tôi được lựa chọn tôi sẽ luôn lựa chọn firebase. Trong phần tiếp theo tôi sẽ trình bầy thêm những ứng dụng nữa từ firebase như push notification trên IOS hay xử lý đa luồng realtime.

Tham khảo