添加自定义单元格支持后MessageKit的Collection View不显示任何单元格
问题描述
我已经通读了MessageKit自定义单元格创建指南,以及相关的Stack Overflow问题。
我尝试创建自定义单元格,以下是我继承自UICollectionViewCell的单元格代码:
import UIKit import MessageKit open class ChatReferenceCell: UICollectionViewCell { @IBOutlet weak var authorLabel: UILabel! @IBOutlet weak var referenceText: UITextView! @IBOutlet weak var participantsLabel: UILabel! public override init(frame: CGRect) { super.init(frame: frame) setupSubviews() } public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setupSubviews() } open func setupSubviews() { } open override func layoutSubviews() { super.layoutSubviews() } open func configure(with message: MessageType, at indexPath: IndexPath, and messagesCollectionView: MessagesCollectionView) { switch message.kind { case .custom(let data): guard let systemMessage = data as? String else { return } referenceText.text = systemMessage default: break } } }
这是自定义单元格对应的XIB文件:
我在ChatViewController中按如下方式配置聊天视图:
messagesCollectionView.register(ChatReferenceCell.self) messagesCollectionView = MessagesCollectionView(frame: .zero, collectionViewLayout: MyCustomMessagesFlowLayout()) messagesCollectionView.messagesDataSource = self messagesCollectionView.messagesLayoutDelegate = self messagesCollectionView.messagesDisplayDelegate = self messagesCollectionView.messageCellDelegate = self
同时配置了自定义布局:
open class CustomMessageSizeCalculator: MessageSizeCalculator { open override func messageContainerSize(for message: MessageType) -> CGSize { // 可自定义该方法实现动态适配内容尺寸,当前示例返回固定尺寸 // 可参考MessageKit默认单元格实现和示例APP学习动态适配逻辑 return CGSize(width: 300, height: 130) } } open class MyCustomMessagesFlowLayout: MessagesCollectionViewFlowLayout { lazy open var customMessageSizeCalculator = CustomMessageSizeCalculator(layout: self) override open func cellSizeCalculatorForItem(at indexPath: IndexPath) -> CellSizeCalculator { let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView) if case .custom = message.kind { return customMessageSizeCalculator } return super.cellSizeCalculatorForItem(at: indexPath); } }
添加自定义单元格之前,我可以在聊天视图控制器中正常添加并显示文本单元格:
尝试添加自定义单元格支持后,界面布局如下:
补充 由于我使用NIB文件,我尝试修正了单元格注册方式,但依旧得到相同结果:messagesCollectionView.register(UINib(nibName: "ChatReferenceCell", bundle: nil), forCellWithReuseIdentifier: "kChatReferenceCollectionViewCell")
解决方案
你的问题由以下几个错误导致,按如下步骤修改即可:
- 修正注册顺序:你先执行了单元格注册,之后才重新初始化
messagesCollectionView,之前的注册操作全部失效。正确顺序是先初始化CollectionView,再执行注册逻辑。 - 修正单元格继承关系:MessageKit要求自定义消息单元格需要继承
MessageCollectionViewCell而非基础的UICollectionViewCell,才能适配框架自带的布局逻辑,避免内容偏移、布局异常的问题。 - 修正复用ID匹配问题:你自定义的复用ID需要和数据源方法中出列单元格的ID保持一致,不要随意自定义不匹配的标识。
- 补全XIB约束:给XIB内的所有控件添加和单元格contentView绑定的完整上下左右边距约束,确保控件可以跟随单元格大小自适应。
具体修改代码
- 调整CollectionView初始化和注册逻辑
// 先初始化CollectionView messagesCollectionView = MessagesCollectionView(frame: .zero, collectionViewLayout: MyCustomMessagesFlowLayout()) // 再注册单元格 messagesCollectionView.register(UINib(nibName: "ChatReferenceCell", bundle: nil), forCellWithReuseIdentifier: "CustomMessageCell") // 最后设置代理 messagesCollectionView.messagesDataSource = self messagesCollectionView.messagesLayoutDelegate = self messagesCollectionView.messagesDisplayDelegate = self messagesCollectionView.messageCellDelegate = self
- 修改自定义单元格父类
import UIKit import MessageKit open class ChatReferenceCell: MessageCollectionViewCell { @IBOutlet weak var authorLabel: UILabel! @IBOutlet weak var referenceText: UITextView! @IBOutlet weak var participantsLabel: UILabel! open override func configure(with message: MessageType, at indexPath: IndexPath, and messagesCollectionView: MessagesCollectionView) { super.configure(with: message, at: indexPath, and: messagesCollectionView) switch message.kind { case .custom(let data): guard let systemMessage = data as? String else { return } referenceText.text = systemMessage default: break } } }
- 在数据源的
cellForItemAt方法中正确返回自定义单元格
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let message = messages[indexPath.section] if case .custom = message.kind { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomMessageCell", for: indexPath) as! ChatReferenceCell cell.configure(with: message, at: indexPath, and: messagesCollectionView) return cell } // 其他类型消息走MessageKit默认逻辑 return messagesCollectionView.dequeueReusableCell(for: indexPath, with: message) }
内容的提问来源于stack exchange,提问作者narner
相关产品推荐
相关产品推荐

