融云记录

312 阅读3分钟

头像问题

融云不保存用户头像昵称,可以使用融云Id去自己服务器查找用户头像昵称,然后缓存在本地融云数据库中,具体方法

此方法为融云的回调方法,可获取到会话列表用户的融云id,在新消息来或者显示会话列表时会调用
func getUserInfo(withUserId userId: String!, completion: ((RCUserInfo?) -> Void)!) 
使用方法里的userId去自己服务器请求昵称和头像,接下来保存到本地融云的缓存中
let currentUserInfo = RCUserInfo.init(userId: userId, name: "nickName", portrait: "userIcon")
///RCIM.shared().currentUserInfo = currentUserInfo此方法为赋值,下面的方法为刷新
RCIM.shared().refreshUserInfoCache(currentUserInfo, withUserId: userId)
completion(currentUserInfo)

不自定义消息的情况下,如何实现多系统通知显示

需要在会话列表实现多种不同类型的系统消息,由于不自定义完全可以实现需要的功能,所以就没有自定义。实现思路:

  • 由于融云本身的系统消息只有System类型,都用System类型发送那么只显示一个系统会话,如果模拟多个用户发送System类型消息呢
  • 后台自定义多个系统消息的id,使用System类型发送系统消息,会话列表就会显示多个系统消息,类似于不同的用户发送消息过来。
  • 系统消息的名称和头像见第一条,同样的方式解决
  • 融云本身的System类型的会话界面是没有输入框的,这也符合我们的需求,只显示消息内容

系统消息,点击的文本变蓝

系统消息内不同的消息里有特别的文字需要显示蓝色,比如“去查看”等,实现思路:

override func willDisplayMessageCell(_ cell: RCMessageBaseCell!, at indexPath: IndexPath!) {
        if cell.isKind(of: RCTextMessageCell.self){
            let textCell : RCTextMessageCell = cell as! RCTextMessageCell
            do{
                let content = textCell.textLabel.text
                let attrStr = try NSMutableAttributedString(data: content?.data(using: String.Encoding.unicode, allowLossyConversion: true) ?? Data(), options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil)
                attrStr.addAttributes([.font:fontN(size: 15)], range: NSMakeRange(0, attrStr.length))
                textCell.textLabel.attributedText = attrStr
                textCell.textLabel.numberOfLines = 0
            }catch let error as NSError {
                print(error.localizedDescription)
            }
        }
    }
  • 系统消息内的特别文字用h5设置好颜色,拿到消息之后我们使用label的h5类型显示
  • 这里我们使用融云willDisplayMessageCell,找到cell的textLabel,拿出它的text,就是我们要显示的内容,把content包装成html格式的赋值给textLabel的attributedText,这样就完成了特别文字显示

会话消息点击头像、点击cell事件

点击头像
override func didTapCellPortrait(_ userId: String!)
点击cell
override func didTapMessageCell(_ model: RCMessageModel!) 

会话列表去掉h5标签

由于会话消息的特别文字需要显示颜色,所以在上面的步骤给消息内容加了html标签,实现了消息内容的特别文字显示,但是在会话列表里html标签没处理的话,标签会显示出来,所以这里的内容也需要做一个去标签处理

override func willReloadTableData(_ dataSource: NSMutableArray!) -> NSMutableArray! {
        for index in 0..<dataSource.count {
            let model = dataSource[index] as! RCConversationModel
            let message = model.lastestMessage as? RCTextMessage
            var str = message?.content
            str = str?.trimmingHTML()
            message?.content = str
        }
        return dataSource
    }
    func trimmingHTML() -> String {
        var str = self ///这里可以替换成想要处理的字符串,通过参数传进来即可
        var indexs: [Int] = []
        for (index, c) in str.enumerated() {
            if String(c) == "<" {
                if let i = indexs.last, str[i] == "<" {
                    break
                }
                indexs.append(index)
            } else if String(c) == ">" {
                if let i = indexs.last, str[i] == ">" {
                    indexs.removeLast()
                }
                indexs.append(index)
            }
        }
        if indexs.count > 0 {
            if let i = indexs.first, str[i] == ">" {
                indexs.removeFirst()
            }
            if let i = indexs.last, str[i] == "<" {
                indexs.removeLast()
            }
        }
        if indexs.count == 0 {
            return str
        }
        var needRemoves: [String] = []
        for i in 0...(indexs.count - 1) / 2 {
            let start = indexs[i * 2]
            let end = indexs[i * 2 + 1] + 1
            for a in start..<end{
                needRemoves.append(String(str[a]))
            }
        }
        for n in needRemoves {
            str = str.replacingOccurrences(of: n, with: "")
        }
        return str
    }

自定义消息

刚开始考虑的自定义消息,稍微研究了一下,具体就是继承于RCMessageContent的类,记得在进行完自定义消息类后,需要在SDKinit之后 connect 之前,注册此自定义消息类。具体查看融云文档doc.rongcloud.cn/im/IOS/5.X/…

消息回调之后有UI操作必须在主线程进行

消息接收到之后如果需要触发UI的显示,必须在主线程进行,开发过程中遇到需要在收到消息后显示倒计时的功能,未能显示倒计时,检查几遍之后发现timer的定时方法在子线程,子线程Loop又没有自动启动,而且UI操作需要在主线程上,所以放在主线程就好了。

DispatchQueue.main.async {}