美文网首页
iOS-Swift-融云自定义消息及其他设置

iOS-Swift-融云自定义消息及其他设置

作者: 爱心随2012 | 来源:发表于2020-07-22 09:51 被阅读0次

    总结所有步骤

    1.自定义消息类型
    2.自定义展示的消息Cell类
    3.自定义消息内容的View(我这里使用xib,大家参考就好)
    4.融云服务器建立连接成功后注册自定义的消息类型,会话页面类注册自定义消息的Cell
    5.发送自定义消息
    6.自定义消息的点击事件
    7.会话页面类的一些处理(界面设置、扩展功能、长按消息撤回转发、自定义地图页面)
    
    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")
        }
        //最后一条消息是自定义消息的时候,可以更改在会话列表显示的类型,为了区分消息类型
        override func conversationDigest() -> String! {
            return "[个人名片]"
        }
        //定义的消息类型名,需要在各个平台上保持一致,以保证消息互通,别以 RC 开头,以免和融云系统冲突
        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
            //我方发送消息-右边布局
            if model.messageDirection == .MessageDirection_SEND {
                locationX = messageContentView.bounds.width - contentV!.bounds.width
                contentV?.isSend = true
                
            //他方发送消息-左边布局
            } else {
                contentV?.isSend = false
            }
            contentV?.setLocationX(x: locationX)
        }
        //MARK:-添加单击手势事件,会话页面的didTapMessageCell方法才会被执行
        @objc func clickAction() {
            delegate.didTapMessageCell?(model)
        }
        //MARK:-添加长按手势事件,会话页面的didLongTouchMessageCell方法才会被执行
        @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 {
                //我方发送消息-右边布局
                if isSend {
                    bgImageV.image = UIImage(named: "liaotian27")
                    contentViewLeft.constant = 15
                    
                //他方发送消息-左边布局
                } 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.发送自定义消息
    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.会话页面类的一些处理(界面设置、扩展功能、长按消息撤回转发、自定义地图页面)
    //重写此方法,防止导航栏自定义按钮被置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
    
        //去除发送地址功能
        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)
        
        //设置某个类型不可撤回,为名片消息添加转发功能
        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: "转发", action: #selector(transmitMessageAction))
            menuItems.insert(transmitItem, at: 0)
            transmitMessage = model
        default:
            break
        }
        return menuItems
    }
    
    //MARK:-转发消息
    @objc func transmitMessageAction() {
        //添加你需要的操作,如跳转到列表页面选择好友或者群来转发
    }
    
    //MARK:-点击位置消息跳转到自定义地图页面(自定义类继承RCLocationViewController,方便自定义UI)
    override func presentLocationViewController(_ locationMessageContent: RCLocationMessage!) {
        let vc = RCIMLocationVC()
        vc.location = locationMessageContent.location
        vc.locationName = locationMessageContent.locationName
        pushViewControllerHideBar(vc, animated: true)
    }
    
    
    以上是我对接融云时候需要做的一些处理,大家对上述处理方式存在疑问或存在隐藏bug,请不吝留言,如果对你有用的话,点个赞哦。

    相关文章

      网友评论

          本文标题:iOS-Swift-融云自定义消息及其他设置

          本文链接:https://www.haomeiwen.com/subject/mofzkktx.html