I followed the latest Example code to (almost) the bone but the didTapMessage event isn't firing when I tap the message text (or a URL). I don't think I'm using a custom cell so I don't think I need to use a custom gesture recognizer.
All messages are appearing correctly but no messages are tappable. On an additional note, I'm using a storyboard to create a view for the chatviewcontroller. I also tried removing the view from storyboard and init the viewcontroller programmatically. Both methods didn't work.
I'm on Swift 5 and using the latest version of MessageKit. Here's the relevant code as follows:
class ChatViewController: MessagesViewController, MessagesDataSource, UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
messagesCollectionView.messageCellDelegate = self
setupCollectionView()
configureMessageCollectionView()
configureMessageInputBar()
}
func configureMessageCollectionView() {
messagesCollectionView.messagesDataSource = self
// messagesCollectionView.messageCellDelegate = self // I moved this critical line directly to viewDidLoad() to troubleshoot but it still didn't work
scrollsToBottomOnKeyboardBeginsEditing = true // default false
maintainPositionOnKeyboardFrameChanged = true // default false
messagesCollectionView.addSubview(refreshControl)
refreshControl.addTarget(self, action: #selector(loadMoreMessages), for: .valueChanged)
}
}
extension ChatViewController: MessageCellDelegate {
func didTapAvatar(in cell: MessageCollectionViewCell) {
print("Avatar tapped")
}
func didTapMessage(in cell: MessageCollectionViewCell) {
print("Message tapped") // Not working
}
extension ChatViewController: MessageLabelDelegate {
func didSelectURL(_ url: URL) {
let safariController = SFSafariViewController(url: url)
present(safariController, animated: true, completion: nil)
print("Link Selected: \(url)") // Not working either
}
extension AdvancedExampleViewController: MessagesDisplayDelegate {
// MARK: - Text Messages
func detectorAttributes(for detector: DetectorType, and message: MessageType, at indexPath: IndexPath) -> [NSAttributedString.Key: Any] {
switch detector {
case .hashtag, .mention:
if isFromCurrentSender(message: message) {
return [.foregroundColor: UIColor.white]
} else {
return [.foregroundColor: UIColor.primaryColor]
}
default: return MessageLabel.defaultAttributes
}
}
func enabledDetectors(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> [DetectorType] {
return [.url, .address, .phoneNumber, .date, .transitInformation, .mention, .hashtag]
}
}
Hi @keithwang5 !
Did you remember to set your messageDisplayDelegate to be the ChatViewController? You need to have
messagesCollectionView.messagesDisplayDelegate = self
in your configureMessageCollectionView method, or viewDidLoad.
In your code sample you also create a _new_ class called AdvancedExampleViewController and conform it to MessageDisplayDelegate where you instead probably meant to create an extension on ChatViewController.
Hello and thank you for responding! I set messageDisplayDelegate to the viewDidLoad of ChatViewController and changed the extension of AdvancedExampleViewController to ChatViewController. It did not work.
In fact, I made a typo in my original post, apologies. AdvancedExampleViewController is an extension (not a class), correctly conforming to MessageDisplayDelegate and messagesCollectionView.messagesDisplayDelegate = self was already declared in viewDidLoad of AdvancedExampleViewController.
What else did I miss?
It would be really helpful if you could post your entire VC code all together (something that I could compile and run and reproduce the issue) or enough of it that it could be run within the example app.
But you can also have a look at this bare minimal example of didSelectUrl working and compare it to your code (you can even download and run that repo to see it working in the simulator): https://github.com/kinoroy/MessageKitUrlDetectorExample/blob/7116d2ed6cba861fc0d2380f0d8ab47ef342e649/MessageKitURLDetectorExample/ChatViewController.swift
Thanks so much for writing the example.
Please have a look at my two VC codes (ChatVC and AdvancedExampleVC) here: https://github.com/keithwang5/sample
I also created a VC in storyboard and assigned AdvancedExampleViewController as the class to that storyboard VC.
You added a tap gesture recognizer to your ChatViewController which is swallowing up touches before they are allowed to be received by MessageKit. You need to tell your gesture that it should allow simultaneous recognition with other gestures by conforming to UIGestureRecognizerDelegate (which I see you've already done) and then adding
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
and your MessageKit delegates will start being called.
Just some advice in the future please try and adapt your sample code so that it can be run within the Example app (meaning remove references to outside libraries like Firebase, GoogleSignIn, etc. You can use the MockMessage struct from the example app for your fake data). This helps us because we don't have to spend time striping out code from your example just to test it, so we can help solve your issue faster, and it also helps you because removing complexity from the situation can help you debug by isolating the issue. 馃槉馃憤
Hello Kino. Thanks so much! That gestureRecognizer method works like a charm!
And well noted on your advice for troubleshooting best practices. I will take note to remove external references and other complexities, and adapt to the Example app in future questions moving forward!
Is this solution available in version 3.4.2?
Most helpful comment
You added a tap gesture recognizer to your ChatViewController which is swallowing up touches before they are allowed to be received by MessageKit. You need to tell your gesture that it should allow simultaneous recognition with other gestures by conforming to
UIGestureRecognizerDelegate(which I see you've already done) and then addingand your MessageKit delegates will start being called.
Just some advice in the future please try and adapt your sample code so that it can be run within the Example app (meaning remove references to outside libraries like Firebase, GoogleSignIn, etc. You can use the
MockMessagestruct from the example app for your fake data). This helps us because we don't have to spend time striping out code from your example just to test it, so we can help solve your issue faster, and it also helps you because removing complexity from the situation can help you debug by isolating the issue. 馃槉馃憤