swiftfirebase-realtime-databasefirebase-authenticationxcode10messagekit

Message Kit Message DataSoure Delegates not called


Using an older version of MessageKit, I made some changes to the library to get rid of the errors due to it being written in an older Swift version.

I integrated the Chat App into my own project, but the message text does not leave the message input bar when the send button is clicked.

Message.Swift File:

struct Message: MessageType {

 let id: String?
 let content: String
 let sentDate: Date
 let sender: SenderType

 var kind: MessageKind {
  if let image = image {
    return .photo(image as! MediaItem)
 } else {
  return .text(content)
 }
}

var messageId: String {
  return id ?? UUID().uuidString
}

var image: UIImage? = nil
var downloadURL: URL? = nil

init(user: User, content: String) {
  sender = Sender(id: user.uid, displayName: AppSettings.displayName)
  self.content = content
  sentDate = Date()
  id = nil
}

init(user: User, image: UIImage) {
  sender = Sender(id: user.uid, displayName: AppSettings.displayName)
  self.image = image
  content = ""
  sentDate = Date()
  id = nil
 }

 init?(document: QueryDocumentSnapshot) {
  let data = document.data()

  guard let sentDate = data["created"] as? Date else {
  return nil
 }
 guard let senderID = data["senderID"] as? String else {
  return nil
}
guard let senderName = data["senderName"] as? String else {
  return nil
}

id = document.documentID

self.sentDate = sentDate
sender = Sender(id: senderID, displayName: senderName)

if let content = data["content"] as? String {
  self.content = content
  downloadURL = nil
} else if let urlString = data["url"] as? String, let url = URL(string: urlString) {
  downloadURL = url
  content = ""
} else {
  return nil
 }
}

}

extension Message: DatabaseRepresentation {

 var representation: [String : Any] {
  var rep: [String : Any] = [
    "created": sentDate,
    "senderID": sender.senderId,
    "senderName": sender.displayName
   ]

  if let url = downloadURL {
  rep["url"] = url.absoluteString
} else {
  rep["content"] = content
}

  return rep
 }

}

extension Message: Comparable {

  static func == (lhs: Message, rhs: Message) -> Bool {
  return lhs.id == rhs.id
 }

   static func < (lhs: Message, rhs: Message) -> Bool {
   return lhs.sentDate < rhs.sentDate
 }

}

ChatViewController:

private func save(_ message: Message) {
reference?.addDocument(data: message.representation) { error in
  if let e = error {
    print("Error sending message: \(e.localizedDescription)")
    return
  }
  
  self.messagesCollectionView.scrollToBottom()
 }
}



extension ChatViewController: MessagesLayoutDelegate {

func avatarSize(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGSize {
return .zero
 }

func footerViewSize(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGSize {
return CGSize(width: 0, height: 8)
}

func heightForLocation(message: MessageType, at indexPath: IndexPath, with maxWidth: CGFloat, in messagesCollectionView: MessagesCollectionView) -> CGFloat {

return 0
}

}


extension ChatViewController: MessagesDataSource {
func currentSender() -> SenderType {
     return Sender(id: user.uid, displayName: AppSettings.displayName)
}

func numberOfSections(in messagesCollectionView: MessagesCollectionView) -> Int {
     return messages.count
}

func numberOfMessages(in messagesCollectionView: MessagesCollectionView) -> Int {
    return messages.count
}


func messageForItem(at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageType {
return messages[indexPath.section]
}

func cellTopLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? {
let name = message.sender.displayName
return NSAttributedString(
  string: name,
  attributes: [
    .font: UIFont.preferredFont(forTextStyle: .caption1),
    .foregroundColor: UIColor(white: 0.3, alpha: 1)
  ]
)
 }

}


extension ChatViewController: MessageInputBarDelegate {

  func messageInputBar(_ inputBar: MessageInputBar, didPressSendButtonWith text: String) {
  let message = Message(user: user, content: text)

  save(message)
  inputBar.inputTextView.text = ""
}

my viewDidLoad():

override func viewDidLoad() {
super.viewDidLoad()

guard let id = channel.id else {
  navigationController?.popViewController(animated: true)
  return
}

reference = db.collection(["channels", id, "thread"].joined(separator: "/"))

messageListener = reference?.addSnapshotListener { querySnapshot, error in
  guard let snapshot = querySnapshot else {
    print("Error listening for channel updates: \(error?.localizedDescription ?? "No error")")
    return
  }
  
  snapshot.documentChanges.forEach { change in
    self.handleDocumentChange(change)
  }
}

  messageInputBar.delegate = self
  messagesCollectionView.messagesDataSource = self
  messagesCollectionView.messagesLayoutDelegate = self
  messagesCollectionView.messagesDisplayDelegate = self
}

Solution

  • It seems, that your pod or carthage file use messageKit with latest version like "3.0.0". So, there is some changes in delegate. Try to change this peace of code:

    extension ChatViewController: MessageInputBarDelegate {
    
      func messageInputBar(_ inputBar: MessageInputBar, didPressSendButtonWith text: String) {
        let message = Message(user: user, content: text)
    
        save(message)
        inputBar.inputTextView.text = ""
    }
    

    with code below

    extension ChatViewController: MessageInputBarDelegate {
      func inputBar(_ inputBar: MessageInputBar, didPressSendButtonWith text: String) {
    
        let message = Message(user: user, content: text)
    
        save(message)
        inputBar.inputTextView.text = ""
      }
    }
    

    If you want to use your old syntax, set messageKit version to some old in your pod or carthage file.