You need to enable JavaScript to run this app. 添加自定义单元格支持后MessageKit的Collection View不显示任何单元格
优惠活动
大模型
产品
解决方案
定价
更多

添加自定义单元格支持后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文件:
自定义单元格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")


解决方案

你的问题由以下几个错误导致,按如下步骤修改即可:

  1. 修正注册顺序:你先执行了单元格注册,之后才重新初始化messagesCollectionView,之前的注册操作全部失效。正确顺序是先初始化CollectionView,再执行注册逻辑。
  2. 修正单元格继承关系:MessageKit要求自定义消息单元格需要继承MessageCollectionViewCell而非基础的UICollectionViewCell,才能适配框架自带的布局逻辑,避免内容偏移、布局异常的问题。
  3. 修正复用ID匹配问题:你自定义的复用ID需要和数据源方法中出列单元格的ID保持一致,不要随意自定义不匹配的标识。
  4. 补全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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 20:45:08