總結所有步驟
1.自定義消息類型
2.自定義展示的消息Cell類
3.自定義消息內容的View(我這里使用xib确丢,大家參考就好)
4.融云服務器建立連接成功后注冊自定義的消息類型矩肩,會話頁面類注冊自定義消息的Cell
5.發(fā)送自定義消息
6.自定義消息的點擊事件
7.會話頁面類的一些處理(界面設置耕皮、擴展功能躺枕、長按消息撤回轉發(fā)家制、自定義地圖頁面)
1.自定義消息類型(UsersModel是自定義的用戶數據model)
let RCBusinessCardCellKey = "Kchat:businessCard" //個人名片
class BusinessCardMessage: RCMessageContent , NSCoding {
var id: Int = -1 //名片用戶id
var title: String = "" //名片昵稱
var detail: String = "" //名片用戶賬號(類似QQ)
var image: String = "" //名片頭像
override init() {
super.init()
}
///初始化
class func messageWithContent(_ model: UsersModel) -> BusinessCardMessage {
let message = BusinessCardMessage()
message.id = model.id
message.title = model.nickname
message.detail = model.kNumber
message.image = model.headimgurl
return message
}
///消息是否存儲暂雹,是否計入未讀數
override class func persistentFlag() -> RCMessagePersistent {
return RCMessagePersistent.MessagePersistent_ISPERSISTED
}
// NSCoding
required init?(coder: NSCoder) {
super.init()
self.id = coder.decodeInteger(forKey: "id")
self.title = "\(coder.decodeObject(forKey: "title") ?? "")"
self.detail = "\(coder.decodeObject(forKey: "detail") ?? "")"
self.image = "\(coder.decodeObject(forKey: "image") ?? "")"
}
func encode(with coder: NSCoder) {
coder.encode(self.id, forKey: "id")
coder.encode(self.title, forKey: "title")
coder.encode(self.detail, forKey: "detail")
coder.encode(self.image, forKey: "image")
}
}
//MARK:*******************代理方法*******************
extension BusinessCardMessage {
///將消息內容編碼成json
override func encode() -> Data! {
let dataDic: NSMutableDictionary = NSMutableDictionary()
dataDic.setValue(self.id, forKey: "id")
dataDic.setValue(self.title, forKey: "title")
dataDic.setValue(self.detail, forKey: "detail")
dataDic.setValue(self.image, forKey: "image")
return try! JSONSerialization.data(withJSONObject: dataDic, options: .prettyPrinted)
}
///將json解碼生成消息內容
override func decode(with data: Data!) {
guard let dic = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as? NSDictionary else {
return
}
self.id = dic.intForKey("id")
self.title = dic.stringForKey("title")
self.detail = dic.stringForKey("detail")
self.image = dic.stringForKey("image")
}
//最后一條消息是自定義消息的時候策治,可以更改在會話列表顯示的類型脓魏,為了區(qū)分消息類型
override func conversationDigest() -> String! {
return "[個人名片]"
}
//定義的消息類型名,需要在各個平臺上保持一致通惫,以保證消息互通,別以 RC 開頭茂翔,以免和融云系統(tǒng)沖突
override class func getObjectName() -> String! {
return RCBusinessCardCellKey
}
}
2.自定義展示的消息Cell類
class BusinessCardMessageCell: RCMessageCell {
static let cellHeight: CGFloat = 84 //消息高度
var contentV: BusinessCardContentV? //消息內容view
//當應用自定義消息時,必須實現該方法來返回cell的Size
override class func size(for model: RCMessageModel!, withCollectionViewWidth collectionViewWidth: CGFloat, referenceExtraHeight extraHeight: CGFloat) -> CGSize {
return CGSize(width: collectionViewWidth, height: cellHeight + extraHeight)
}
//設置當前消息Cell的數據模型
override func setDataModel(_ model: RCMessageModel!) {
super.setDataModel(model)
setContentV(model)
}
//設置消息UI
func setContentV(_ model: RCMessageModel) {
if contentV == nil {
contentV = BusinessCardContentV().initContentV()
contentV?.model = model.content
//添加自定義消息點擊事件
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(clickAction))
contentV?.addGestureRecognizer(tapGesture)
//添加自定義消息長按事件
let longGesture: UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longAction(_:)))
contentV?.addGestureRecognizer(longGesture)
messageContentView?.addSubview(contentV!)
}
var locationX: CGFloat = 0.0
//我方發(fā)送消息-右邊布局
if model.messageDirection == .MessageDirection_SEND {
locationX = messageContentView.bounds.width - contentV!.bounds.width
contentV?.isSend = true
//他方發(fā)送消息-左邊布局
} else {
contentV?.isSend = false
}
contentV?.setLocationX(x: locationX)
}
//MARK:-添加單擊手勢事件履腋,會話頁面的didTapMessageCell方法才會被執(zhí)行
@objc func clickAction() {
delegate.didTapMessageCell?(model)
}
//MARK:-添加長按手勢事件珊燎,會話頁面的didLongTouchMessageCell方法才會被執(zhí)行
@objc func longAction(_ longGesture: UILongPressGestureRecognizer) {
if longGesture.state != .began { return }
delegate.didLongTouchMessageCell?(model, in: self)
}
}
3.自定義消息內容的View(我這里使用xib,大家參考就好)
class BusinessCardContentV: UIView {
@IBOutlet weak var bgImageV: UIImageView!
@IBOutlet weak var contentViewLeft: NSLayoutConstraint!
@IBOutlet weak var imageV: UIImageView!
@IBOutlet weak var nameL: UILabel!
@IBOutlet weak var detailL: UILabel!
private var _model: RCMessageContent?
var model: RCMessageContent? {
set(newValue) {
_model = newValue
if newValue == nil { return }
guard let messageModel = newValue as? BusinessCardMessage else {
return
}
imageV.loadImage(imgUrl: messageModel.image, defaultImage: "morentu")
imageV.setContentFit()
nameL.text = messageModel.title
detailL.text = messageModel.detail
}
get { return _model }
}
var isSend: Bool = false {
didSet {
//我方發(fā)送消息-右邊布局
if isSend {
bgImageV.image = UIImage(named: "liaotian27")
contentViewLeft.constant = 15
//他方發(fā)送消息-左邊布局
} else {
bgImageV.image = UIImage(named: "liaotian26")
contentViewLeft.constant = 21
}
}
}
//初始化
func initContentV() -> BusinessCardContentV {
let contentV: BusinessCardContentV = Bundle.main.loadNibNamed("BusinessCardContentV", owner: nil, options: nil)?.first as! BusinessCardContentV
contentV.frame = CGRect(x: 0, y: 0, width: 235, height: 84)
return contentV
}
}
4.融云服務器建立連接成功后注冊自定義的消息類型府树,會話頁面類注冊自定義消息的Cell
//融云服務器建立連接成功后注冊自定義的消息類型
RCIM.shared().registerMessageType(BusinessCardMessage.self)
//繼承RCConversationViewController的會話頁面注冊自定義消息的Cell
register(BusinessCardMessageCell.self, forMessageClass: BusinessCardMessage.self)
5.發(fā)送自定義消息
let message: BusinessCardMessage = BusinessCardMessage.messageWithContent(usersModel)
sendMessage(message, pushContent: "[個人名片]\(message.title)")
6.自定義消息的點擊事件
//MARK:-點擊消息
override func didTapMessageCell(_ model: RCMessageModel!) {
super.didTapMessageCell(model)
switch model.objectName {
case RCBusinessCardCellKey: //名片
//添加你需要的操作
default:
break
}
}
7.會話頁面類的一些處理(界面設置俐末、擴展功能、長按消息撤回轉發(fā)奄侠、自定義地圖頁面)
//重寫此方法卓箫,防止導航欄自定義按鈕被置nil
override func notifyUpdateUnreadMessageCount() { }
//MARK:-設置CollectionView的屬性
func setCollectionViewProperty() {
conversationMessageCollectionView.backgroundColor = UIColor.BackgroundColor()
conversationMessageCollectionView.showsVerticalScrollIndicator = false
//修改背景顏色
chatSessionInputBarControl.inputTextView.superview?.backgroundColor = RGBA(234, 237, 243, 1)
chatSessionInputBarControl.pluginBoardView.contentView.backgroundColor = RGBA(234, 237, 243, 1)
//修改輸入框
chatSessionInputBarControl.inputTextView.layer.borderWidth = 0
chatSessionInputBarControl.inputTextView.layer.cornerRadius = 6
//去除發(fā)送地址功能
chatSessionInputBarControl.pluginBoardView.removeItem(at: 1003)
//添加擴展功能
chatSessionInputBarControl.pluginBoardView.insertItem(with: UIImage(named: "liaotian23"), title: "名片", tag: 202)
//自定義消息
register(BusinessCardMessageCell.self, forMessageClass: BusinessCardMessage.self)
}
//MARK:-擴展功能板的點擊回調
override func pluginBoardView(_ pluginBoardView: RCPluginBoardView!, clickedItemWithTag tag: Int) {
super.pluginBoardView(pluginBoardView, clickedItemWithTag: tag)
weak var weakSelf = self
switch tag {
case 202: //名片
//添加你需要的操作
default: break
}
}
//MARK:-長按消息的回調
override func didLongTouchMessageCell(_ model: RCMessageModel!, in view: UIView!) {
super.didLongTouchMessageCell(model, in: view)
}
override func getLongTouchMessageCellMenuList(_ model: RCMessageModel!) -> [UIMenuItem]! {
var menuItems: [UIMenuItem] = super.getLongTouchMessageCellMenuList(model)
//設置某個類型不可撤回,為名片消息添加轉發(fā)功能
switch model.objectName {
case RCXXXXXXXXCellKey:
for i in 0 ..< menuItems.count {
if menuItems[i].title != "撤回" { continue }
menuItems.remove(at: i)
break
}
case RCBusinessCardCellKey:
let transmitItem: UIMenuItem = UIMenuItem(title: "轉發(fā)", action: #selector(transmitMessageAction))
menuItems.insert(transmitItem, at: 0)
transmitMessage = model
default:
break
}
return menuItems
}
//MARK:-轉發(fā)消息
@objc func transmitMessageAction() {
//添加你需要的操作垄潮,如跳轉到列表頁面選擇好友或者群來轉發(fā)
}
//MARK:-點擊位置消息跳轉到自定義地圖頁面(自定義類繼承RCLocationViewController烹卒,方便自定義UI)
override func presentLocationViewController(_ locationMessageContent: RCLocationMessage!) {
let vc = RCIMLocationVC()
vc.location = locationMessageContent.location
vc.locationName = locationMessageContent.locationName
pushViewControllerHideBar(vc, animated: true)
}
以上是我對接融云時候需要做的一些處理闷盔,大家對上述處理方式存在疑問或存在隱藏bug,請不吝留言旅急,如果對你有用的話逢勾,點個贊哦。