jessesquires/JSQMessagesViewController

custom cell how to set delegate?

pig12301230 opened this issue · 8 comments

New issue checklist

General information

  • JSQMessagesViewController version: 7.3.4
  • iOS version: 10
  • Devices/Simulators: iPhone
  • Reproducible in the demo project? (Yes/No):
  • Any related issues:

What happened?

I create my own custom cell and shows correctly
in viewDidLoad

self.collectionView.register(UINib(nibName: "CustomUrlMessageCellIncoming", bundle: nil), forCellWithReuseIdentifier: "CustomUrlMessageCellIncoming")

and

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomUrlMessageCellIncoming", for: indexPath) as!
                CustomUrlMessageCellIncoming

but override function can't work.

override func collectionView(_ collectionView: JSQMessagesCollectionView!, didTapMessageBubbleAt indexPath: IndexPath!)

I don't know where delegate set , it always nil

it's my customCell class

import Foundation
import JSQMessagesViewController

class CustomUrlMessageCellIncoming: JSQMessagesCollectionViewCellIncoming {
    @IBOutlet weak var urlView: UrlView!
    // MARK: - Overrides
    @IBOutlet weak var urlImgView: UIImageView!
    @IBOutlet weak var messageTextView: UITextView!
    @IBOutlet weak var containerView: UIView!
    @IBOutlet weak var title: UILabel!
    @IBOutlet weak var desc: UILabel!
    @IBOutlet weak var avatarImage: UIImageView!
    @IBOutlet weak var avatarContainer: UIView!

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    override class func nib() -> UINib {
        return UINib (nibName: "CustomUrlMessageCellIncoming", bundle: Bundle.main)
    }
    
    override class func cellReuseIdentifier() -> String {
        return "CustomUrlMessageCellIncoming"
    }
    
    override class func mediaCellReuseIdentifier() -> String {
        return "CustomUrlMessageCellIncoming"
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        messageBubbleTopLabel.textAlignment = .left
        cellBottomLabel.textAlignment = .left
        let tap = UITapGestureRecognizer(target: self, action: #selector(self.jsq_handleTapGesture))
        addGestureRecognizer(tap)
//        tapGestureRecognizer = tap

    }
    
    func jsq_handleTapGesture(_ tap: UITapGestureRecognizer) {
        let touchPt: CGPoint = tap.location(in: self)
        if avatarContainer.frame.contains(touchPt) {
            self.delegate.messagesCollectionViewCellDidTapAvatar(self)
            print("ava")
        }
        else if containerView.frame.contains(touchPt) {
            self.delegate.messagesCollectionViewCellDidTapMessageBubble(self)
            print("mess")
        }
        else {
            self.delegate.messagesCollectionViewCellDidTap(self, atPosition: touchPt)
            print("other")
        }
    }
}

@pig12301230, are you talking about the Collection View or the Cell? If latter, it should something like self.delegate(self is an instance of a cell class).

@Lucashuang0802, I hope that my custom cell can do as well as JSQMessageViewCell can
tap avatarImageView, tap messageBubble something like this

but I have no idea where to set delegate for my own cell , because the origin cell.delegete has been set at super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell

thank you for help

@pig12301230, if I understand correctly, you are trying to detect a gesture and perform some tasks on it. There are a lot of gesture recognizer classes you can use to enable tapping on a UIView instance as well as pinching, rotating etc. As for what you showed, that is the method to get a specific cell from a given NSIndexPath. There is nothing to do with cell.delegate.

As this is not a library-related issue, I would suggest you to go to read some general iOS programming stuff like https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/Protocol.html

Hope it helps.

@Lucashuang0802, my question is when I do incoming/outgoing custom cell.
My cell is copy from origin cell and subclass.
and I add gesture on cell and it can work. but how to call

self.delegate.messagesCollectionViewCellDidTapAvatar(self)
self.delegate.messagesCollectionViewCellDidTapMessageBubble(self)

because my own cell does't get JSQMessagesCollectionViewCellDelegate

@pig12301230, I see what you are saying. The delegate object is set through JSQMessagesCollectionViewCell. You can search JSQMessagesCollectionViewCell on Xcode to locate the class and delegate object. Normally, you should be able to set by cell.delegate = self.

@Lucashuang0802,

 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let msg = messages[indexPath.item]
        if let urlmedia = msg.media as? UrlMediaItem{
            if (msg.senderId != senderId) {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomUrlMessageCellIncoming", for: indexPath) as! CustomUrlMessageCellIncoming
                cell.delegate = self as! JSQMessagesCollectionViewCellDelegate

and it will show error:
Could not cast value of type 'ChatRoomViewController' (0x1097d2010) to 'JSQMessagesCollectionViewCellDelegate' (0x10abdec40)

it bothers me for a few days, thanks for you help

In your class declaration for ChatRoomViewController, I assume you are extending JSQMessagesViewController like this

class ChatRoomViewController : JSQMessagesViewController

But the error means you are not i plementing the required protocol you are teying to cast to, so add the protocol like such:

class ChatRoomViewController : JSQMessagesViewController, JSQMessagesCollectionViewCellDelegate

Then implement all the requires functions.

I dont have my computer in front of me, so I cannot confirm if this is he correct solution, as I am basing it inly on the error message, and the provided code snipet. Additionally, my Swift is getting rusty.
For any required functions from the delegate protocol, if you dont want to modify the default behavior, then you should be able to call the super class function, if it inplementa the protocol, otherwise, do nothing in your functions that you dont want to implement from the delegate protocol.

Hello everyone!

I'm sorry to inform the community that I'm officially deprecating this project. 😢 Please read my blog post for details:

http://www.jessesquires.com/blog/officially-deprecating-jsqmessagesviewcontroller/

Thus, I'm closing all issues and pull requests and making the necessary updates to formally deprecate the library. I'm sorry if this is unexpected or disappointing. Please know that this was an extremely difficult decision to make. I'd like to thank everyone here for contributing and making this project so great. It was a fun 4 years. 😊

Thanks for understanding,
— jsq