入職新公司,是一家做社交產品的,剛到時候已經完成了部分功能,上個開發人員采用的是storyboard進行界面搭建,對於后期維護,可想而知,費勁。
為了節省開發周期,即時通訊采用的是融雲的IMKit,可偷懶一時爽,后台的改版,讓我變得心累。
IMKit是融雲為了幫用戶搭的聊天框架,節省開發周期的同時,卻也限制界面的可擴展性。
框架沒選好,開發一直爽(爽到爆,爽到讓你哭)。
一次次修改,一次次出現問題,IMKit讓我想哭。
在改版了3次之后,決定徹底放棄IMKit,采用IMLib,所有的界面自己來做。而且融雲IMKit的UX根本無法滿足我們的需要,作為社交產品,對於用戶體驗要求是相當高,體驗不好,對產品來說,這是致命問題。
最終決定采用老外寫的一個即時聊天框架MessageKit。不得不說,人家是牛逼的。
GitHub地址:https://github.com/MessageKit/MessageKit
聊天列表采用的是UICollectionView,對常用聊天功能也進行了封裝,支持文字,圖片,語音,視頻等。開發過程中,只許替換自己的內容即可。【效果圖:看鏈接】
一、布局:
所有的界面都是圍繞着控制器MessagesViewController進行,界面采用了一個UICollectionView用於展示聊天信息,在底部是一個封裝的聊天輸入框InputBarAccessoryView,在控制器中實現了對鍵盤監聽,用於修改界面的位置。
/// The `MessagesCollectionView` managed by the messages view controller object. open var messagesCollectionView = MessagesCollectionView() /// The `InputBarAccessoryView` used as the `inputAccessoryView` in the view controller. open var messageInputBar = InputBarAccessoryView()
所有的cell繼承MessageContentCell或MessageCollectionViewCell
MessageContentCell是在MessageCollectionViewCell基礎上做了一些聊天中常用的封裝,比如:頭像、昵稱、消息內容已經做好了布局,只需要填充內容即可。
MessageCollectionViewCell是繼承自UICollectionViewCell這就需要有開發人員自己完成消息的界面布局了。
動態Cell的高度,都繼承CellSizeCalculator類,在該類中已經提供了一些super 方法,
/// The layout object for which the cell size calculator is used. public weak var layout: UICollectionViewFlowLayout? /// Used to configure the layout attributes for a given cell. /// /// - Parameters: /// - attributes: The attributes of the cell. /// The default does nothing open func configure(attributes: UICollectionViewLayoutAttributes) {} /// Used to size an item at a given `IndexPath`. /// /// - Parameters: /// - indexPath: The `IndexPath` of the item to be displayed. /// The default return .zero open func sizeForItem(at indexPath: IndexPath) -> CGSize { return .zero }
所有子類的高度Calculator都可以在此基礎上進行override。如下:
open override func configure(attributes: UICollectionViewLayoutAttributes) { super.configure(attributes: attributes) guard let attributes = attributes as? MessagesCollectionViewLayoutAttributes else { return } let dataSource = messagesLayout.messagesDataSource let indexPath = attributes.indexPath let message = dataSource.messageForItem(at: indexPath, in: messagesLayout.messagesCollectionView) attributes.messageLabelInsets = messageLabelInsets(for: message) attributes.messageLabelFont = messageLabelFont switch message.kind { case .attributedText(let text): guard !text.string.isEmpty else { return } guard let font = text.attribute(.font, at: 0, effectiveRange: nil) as? UIFont else { return } attributes.messageLabelFont = font default: break } }
二、消息內容
所有的傳值,都是通過delegate來實現的,
//cell的點擊響應 func didPauseAudio(in cell: AudioMessageCell) func didStartAudio(in cell: AudioMessageCell) //cell的數據源 func messageForItem(at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageType func cellTopLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString?
使用MessageKit能有效幫助快速搭建聊天界面。
