vue集成环信IM
vue 集成环信im 简单demo
环信AppKey:1106190415055331#test
测试账号: test1 123456 test2 123456 test3 123456
默认登录test1
用vuex统一管理聊天对象、聊天信息等
点击相应的对象,发送文本
1. 引入环信依赖

2. vuex 环信前期准备全局状态控制
import {dotData} from '@/utils'
import Vue from 'vue'
// im聊天状态
const IM_CHART_DIALOG = {
  state: {
    visible: false, // 显示隐藏
    rosterList: [], // 好友列表
    groupList: [],  // 群组列表
    groupMessageMap: {}, // 聊天信息集合
    groupMessageHistoryMap: {}, // 历史消息
    currentGroupId: '', // 当前活动
    extMap: {}, // 附加信息
    eNameMap: {}, // 用户名信息
    disabledGroupId: [],
    groupIdMap: {}, // 群消息
    readonlyGroupIdArr: [] // 只读的groupId
  },
  mutations: { // 修改状态
    SET_IM_CHART_DIALOG_VISIBLE(state, {visible}) { // 弹窗可见/隐藏
      state.visible = visible
    },
    SET_IM_CHART_ROSTERLIST(state, rosterList) {
      state.rosterList = rosterList
    },
    SET_IM_CHART_GROUPLIST(state, groupList) {
      state.groupList = groupList
    },
    PUSH_IM_CHART_DIALOG_GROUP_MESSAGE(state, {message, groupId}) { // 用户聊天信息
      let chart = state.groupMessageMap[groupId] || []
      chart.push(message)
      Vue.set(state.groupMessageMap, groupId, chart)
    },
    UN_SHIFT_IM_CHART_DIALOG_GROUP_MESSAGE(state, {message, groupId}) { // 用户聊天信息
      let chart = state.groupMessageMap[groupId] || []
      chart.unshift(message)
      Vue.set(state.groupMessageMap, groupId, chart)
    },
    REMOVE_IM_CHART_DIALOG_GROUP_MESSAGE(state, groupId) { // 移除一个群聊
      let chart = state.groupMessageMap
      delete chart[groupId]
      state.groupMessageMap = chart
    },
    SET_IM_CHART_DIALOG_GROUP_ID(state, groupId) { // 设置当前用户组
      state.currentGroupId = groupId
    },
    SET_IM_CHART_EXT_MAP(state, {groupId, ext}) { // 设置group 附加信息
      if (!state.extMap[groupId]) {
        Vue.set(state.extMap, groupId, ext)
      }
    },
    REMOVE_IM_CHART_EXT_MAP(state, groupId) { // 移除一个群聊追加消息
      let ext = state.extMap
      delete ext[groupId]
      state.extMap = ext
    },
    REMOVE_IM_CHART_GROUP_ID(state, groupId) {
      let groupIdMap = state.groupIdMap
      delete groupIdMap[groupId]
      state.groupIdMap = groupIdMap
    },
    // eName 和用户进行映射
    SET_IM_CHART_DIALOG_MEMBER_E_NAME(state, {eName, member}) {
      Vue.set(state.eNameMap, eName, member)
    },
    // 使当前用户组消息已读
    SET_IM_CHART_DIALOG_GROUP_ID_READ(state, groupId) {
      if (state.visible) {
        let chart = state.groupMessageMap[groupId] || []
        chart.forEach(v => {
          Vue.set(v, 'isRead', true)
        })
        Vue.set(state.groupMessageMap, groupId, chart)
      }
    },
    // 禁用的groupId
    PUSH_IM_CHART_DIALOG_DISABLE_GROUP_ID(state, groupId) {
      state.disabledGroupId.push(groupId)
    },
    // 群组信息
    SET_IM_CHART_DIALOG_GROUP_ID_INFO(state, {groupId, info}) {
      if (groupId) {
        Vue.set(state.groupIdMap, groupId, info)
      }
    },
    // 清除群消息
    CLEAR_IM_CHART_DIALOG_GROUP_ID_INFO(state) {
      state.groupIdMap = {}
    },
    // 历史记录拉取 第一次拉取为真
    SET_IM_GROUP_MESSAGE_HISTORY_FIRST(state, {groupId}) {
      let obj = state.groupMessageHistoryMap[groupId] || {}
      Vue.set(obj, 'first', true)
      Vue.set(state.groupMessageHistoryMap, groupId, obj)
    },
    // 历史记录拉取 已经没有数据了
    SET_IM_GROUP_MESSAGE_HISTORY_OVER(state, {groupId}) {
      let obj = state.groupMessageHistoryMap[groupId] || {}
      Vue.set(obj, 'over', true)
      Vue.set(state.groupMessageHistoryMap, groupId, obj)
    },
    // 只读的消息列表
    SET_IM_READ_ONLY_GROUP_ID(state, {groupId}) {
      state.readonlyGroupIdArr.push(groupId)
    }
  },
  actions: { // 调用方法(接收传进来的参数)
    // 展示弹窗
    SET_IM_CHART_DIALOG_VISIBLE({commit}, {visible}) { // 弹窗可见
      commit('SET_IM_CHART_DIALOG_VISIBLE', {visible})
    },
    // 好友列表
    SET_IM_CHART_ROSTERLIST({commit}, rosterList) {
      commit('SET_IM_CHART_ROSTERLIST', rosterList)
    },
    // 群组列表
    SET_IM_CHART_GROUPLIST({commit}, groupList) {
      commit('SET_IM_CHART_GROUPLIST', groupList)
    },
    // 添加消息
    PUSH_IM_CHART_DIALOG_GROUP_MESSAGE({commit}, message) { // 聊天信息组
      const groupId = dotData(message, 'groupId')
      const ext = dotData(message, 'ext')
      delete message.ext
      commit('PUSH_IM_CHART_DIALOG_GROUP_MESSAGE', {groupId, message})
      commit('SET_IM_CHART_EXT_MAP', {groupId, ext}) // 设置附加消息
    },
    UN_SHIFT_IM_CHART_DIALOG_GROUP_MESSAGE({commit}, message) { // 聊天信息组
      const groupId = dotData(message, 'groupId')
      const ext = dotData(message, 'ext')
      delete message.ext
      commit('UN_SHIFT_IM_CHART_DIALOG_GROUP_MESSAGE', {groupId, message})
      commit('SET_IM_CHART_EXT_MAP', {groupId, ext}) // 设置附加消息
    },
    REMOVE_IM_CHART_DIALOG_GROUP_ID({commit, getters}, groupId) {
      commit('REMOVE_IM_CHART_DIALOG_GROUP_MESSAGE', groupId) // 移除消息
      commit('REMOVE_IM_CHART_EXT_MAP', groupId) // 移除附加消息
      // 移除一个群
      commit('REMOVE_IM_CHART_GROUP_ID', groupId)
      commit('PUSH_IM_CHART_DIALOG_DISABLE_GROUP_ID', groupId)
      if (groupId === getters.GET_IM_CHART_DIALOG_GROUP_ID) {
        commit('SET_IM_CHART_DIALOG_GROUP_ID', '')
      }
    },
    // 添加追加信息
    SET_IM_CHART_EXT_MAP({commit}, {groupId, ext}) {
      commit('SET_IM_CHART_EXT_MAP', {groupId, ext})
    },
    // 设置当前groupId
    SET_IM_CHART_DIALOG_GROUP_ID({commit}, groupId) {
      commit('SET_IM_CHART_DIALOG_GROUP_ID', groupId)
      commit('SET_IM_CHART_DIALOG_GROUP_ID_READ', groupId)
    },
    // 添加禁用的groupId
    PUSH_IM_CHART_DIALOG_DISABLE_GROUP_ID({commit, getters}, groupId) {
      if (groupId) {
        commit('PUSH_IM_CHART_DIALOG_DISABLE_GROUP_ID', groupId)
        if (groupId === getters.GET_IM_CHART_DIALOG_GROUP_ID) {
          commit('SET_IM_CHART_DIALOG_GROUP_ID', '')
        }
      }
    },
    SET_IM_CHART_DIALOG_GROUP_ID_INFO({commit}, {groupId, info}) { // 设置群聊信息
      commit('SET_IM_CHART_DIALOG_GROUP_ID_INFO', {groupId, info})
      if (Array.isArray(info.members)) {
        info.members.forEach(v => {
          commit('SET_IM_CHART_DIALOG_MEMBER_E_NAME', {eName: v.userEasemobName, member: v})
        })
      }
    },
    CLEAR_IM_CHART_DIALOG_GROUP_ID_INFO({commit}) { // 清空群信息
      commit('CLEAR_IM_CHART_DIALOG_GROUP_ID_INFO')
    },
    SET_IM_GROUP_MESSAGE_HISTORY_FIRST({commit}, {groupId}) { // 第一次访问历史消息
      commit('SET_IM_GROUP_MESSAGE_HISTORY_FIRST', {groupId})
    },
    SET_IM_GROUP_MESSAGE_HISTORY_OVER({commit}, {groupId}) { // 已无历史消息
      commit('SET_IM_GROUP_MESSAGE_HISTORY_OVER', {groupId})
    },
    SET_IM_READ_ONLY_GROUP_ID({commit}, {groupId}) { // 只读消息
      commit('SET_IM_READ_ONLY_GROUP_ID', {groupId})
    }
  },
  getters: { // 弹窗展示
    GET_IM_CHART_DIALOG_VISIBLE: state => {
      return state.visible
    },
    GET_IM_CHART_ROSTERLIST: state => {
      return state.rosterList || []
    },
    GET_IM_CHART_GROUPLIST: state => {
      return state.groupList || []
    },
    GET_IM_CHART_DIALOG_GROUP_ID: state => { // 获取当前groupId
      return state.currentGroupId
    },
    GET_IM_CHART_EXT_MAP: (state) => (groupId) => { // 根据用户组获取
      if (state.extMap[groupId]) {
        return state.extMap[groupId]
      }
    },
    GET_IM_CHART_DIALOG_GROUP_MESSAGE: (state) => (groupId) => { // 获取消息组
      if (groupId) {
        return state.groupMessageMap[groupId] || []
      }
      return []
    },
    GET_IM_CHART_DIALOG_MEMBER_E_NAME: (state) => (eName) => { // 根据环信name 获取用户信息
      if (eName) {
        return state.eNameMap[eName] || {}
      }
      return state.eNameMap
    },
    // 获取未读消息条数
    GET_IM_CHART_DIALOG_UN_READ_LENGTH: (state, getters) => (groupId) => { // 根据环信name 获取用户信息
      if (Array.isArray(groupId)) {
        let temp = 0
        groupId.forEach(id => {
          temp += getters.GET_IM_CHART_DIALOG_GROUP_MESSAGE(groupId).filter(v => v.isRead === false).length
        })
        return temp
      } else {
        return getters.GET_IM_CHART_DIALOG_GROUP_MESSAGE(groupId).filter(v => v.isRead === false).length
      }
    },
    // 全部未读消息
    GET_IM_CHART_DIALOG_ALL_UN_READ_LENGTH: (state) => { // 根据环信name 获取用户信息
      let temp = 0
      for (let k in state.groupMessageMap) {
        if (Array.isArray(state.groupMessageMap[k])) {
          temp += state.groupMessageMap[k].filter(v => v.isRead === false).length
        }
      }
      return temp
    },
    // 获取最后一条消息
    GET_IM_CHART_DIALOG_LAST_MESSAGE: (state, getters) => (groupId) => {
      let temp = ''
      if (Array.isArray(groupId)) {
        groupId.forEach(id => {
          let charts = getters.GET_IM_CHART_DIALOG_GROUP_MESSAGE(id)
          let lastChart = ''
          if (charts.length) {
            lastChart = charts[charts.length - 1]
          }
          if (temp) {
            if (lastChart) {
              if (temp.timeStr < lastChart.timeStr) {
                temp = lastChart
              }
            }
          } else {
            if (lastChart) {
              temp = lastChart
            }
          }
        })
      } else {
        let charts = getters.GET_IM_CHART_DIALOG_GROUP_MESSAGE(groupId)
        if (charts.length) {
          temp = charts[charts.length - 1]
        }
      }
      if (temp) {
        switch (temp.fileType) {
          case 'audio':
            return '[语音]'
          case 'image':
            return '[图片]'
          default :
            return temp.sourceMsg
        }
      }
    },
    // 历史消息对象
    GET_IM_GROUP_MESSAGE_HISTORY: (state) => (groupId) => {
      return dotData(state.groupMessageHistoryMap, groupId) || {}
    },
    // 是只读消息
    IS_IM_READ_ONLY_GROUP_ID: (state) => (groupId) => {
      return state.readonlyGroupIdArr.indexOf(groupId) >= 0
    }
  }
}
export default IM_CHART_DIALOG3. 构建环信实例
import store from '@/store'
import {alert, dotData} from '@/utils'
import moment from 'moment' export const Easemob = class Easemob {
static instance = null
connection = null
config = {}
username = ''
WebIM = window.WebIM // 初始化
constructor() {
if (Easemob.instance) {
return Easemob.instance
}
this.config = window.WebIM.config
Easemob.instance = this
} // 获取当前时间
_getTimeString() {
return moment().format('YYYY-MM-DD HH:mm:ss')
} // 获取连接
getConnection() {
if (!this.connection) {
const Connection = window.WebIM.connection
this.connection = new Connection({
isMultiLoginSessions: this.config.isMultiLoginSessions,
https: typeof this.config.https === 'boolean' ? this.config.https : location.protocol === 'https:',
url: this.config.xmppURL,
isAutoLogin: true,
heartBeatWait: this.config.heartBeatWait,
autoReconnectNumMax: this.config.autoReconnectNumMax,
autoReconnectInterval: this.config.autoReconnectInterval,
apiUrl: this.config.apiURL
})
}
return this.connection
} // 发送时追加信息
appendMessage(message, className = 'in') {
message = this.createClassNameAndTime(message, className)
message = this._setExt(message)
return message
} // 添加时间和来源
createClassNameAndTime(message, className = 'in') {
message.className = className
message.timeStr = message.timeStr || this._getTimeString()
message.loginUserName = this.username
return message
} // 设置追加信息
_setExt(message) {
return message
} // 发送已阅回执
readMessage(message) {
let ImMessage = this.WebIM.message
const id = this.getConnection().getUniqueId()
let msg = new ImMessage('read', id)
msg.set({
id: message.id,
to: message.from
})
this.getConnection().send(msg.body)
} // 登陆
login(username, password) {
this.getConnection().open({
apiUrl: this.config.apiURL,
user: username,
pwd: password,
appKey: this.config.appkey
}) const that = this this.connection.listen({
onOpened(message) {
that.username = username // 获取好友
this.getRoster({
success: roster => {
store.dispatch('SET_IM_CHART_ROSTERLIST', roster)
},
error: e => {
console.log(e)
}
})
// 获取群组
this.getGroup({
success: group => {
store.dispatch('SET_IM_CHART_GROUPLIST', group.data)
},
error: e => {
console.log(e)
}
})
},
// 文本消息
onTextMessage(message) {
message = that.createClassNameAndTime(message)
// 处理表情
if (typeof message.sourceMsg === 'string') {
Object.keys(that.config.emoConfig.map).forEach(v => {
message.data = message.sourceMsg = message.sourceMsg.replace(new RegExp(v, 'g'), `<img src="${that.config.emoConfig.path + that.config.emoConfig.map[v]}" />`)
})
}
let type = dotData(message, 'type')
if (type === 'groupchat') { // 群组消息
message.groupId = message.to
if (store.getters.GET_IM_CHART_DIALOG_GROUP_ID !== message.groupId || store.getters.GET_IM_CHART_DIALOG_VISIBLE === false) {
message.isRead = false
}
store.dispatch('PUSH_IM_CHART_DIALOG_GROUP_MESSAGE', message)
} else {
message.groupId = message.from
store.dispatch('PUSH_IM_CHART_DIALOG_GROUP_MESSAGE', message)
}
},
// 穿透消息
onCmdMessage(message) {
message.sourceMsg = '发起对话'
message.data = '发起对话'
message = that.createClassNameAndTime(message)
let type = dotData(message, 'type')
if (type === 'groupchat') {
message.from = message.to
}
store.dispatch('PUSH_IM_CHART_DIALOG_GROUP_MESSAGE', message)
},
// 图片消息
onPictureMessage(message) {
message = that.createClassNameAndTime(message)
message.fileType = 'image'
let type = dotData(message, 'type')
if (type === 'groupchat') { // 群组消息
message.groupId = message.to
if (store.getters.GET_IM_CHART_DIALOG_GROUP_ID !== message.groupId || store.getters.GET_IM_CHART_DIALOG_VISIBLE === false) {
message.isRead = false
}
store.dispatch('PUSH_IM_CHART_DIALOG_GROUP_MESSAGE', message)
}
},
// 音频消息
onAudioMessage(message) {
let options = {url: message.url} options.onFileDownloadComplete = (response) => {
message.objectURL = that.WebIM.utils.parseDownloadResponse.call(that.getConnection(), response)
message = that.createClassNameAndTime(message)
message.fileType = 'audio'
let type = dotData(message, 'type')
if (type === 'groupchat') { // 群组消息
message.groupId = message.to
if (store.getters.GET_IM_CHART_DIALOG_GROUP_ID !== message.groupId || store.getters.GET_IM_CHART_DIALOG_VISIBLE === false) {
message.isRead = false
}
store.dispatch('PUSH_IM_CHART_DIALOG_GROUP_MESSAGE', message)
}
} options.onFileDownloadError = () => {
// 音频下载失败
} // 通知服务器将音频转为mp3
options.headers = {
'Accept': 'audio/mp3'
} that.WebIM.utils.download.call(that.getConnection(), options)
},
onEmojiMessage: (message) => {
let data = message.data
for (let i = 0, l = data.length; i < l; i++) {
}
},
onError(message) {
that.handError(message)
}
})
return this.connection
} // 处理报错
handError(error) {
let err = 'im报错:'
console.error(error)
switch (error.type) {
case 7 :
alert(err + '客户端网络中断')
break
case 8 :
alert(err + '多端登录,被踢下线')
break
case 16 :
alert(err + '服务端关闭了链接')
break
case 31 :
alert(err + '处理下行消息出错,try/catch抛出异常')
break
case 32 :
alert(err + '客户端断线')
break
case 33 :
alert(err + '客户端退出登录')
break
case 34 :
alert(err + '同一浏览器打开标签页超过上限')
break
case 402 :
alert(err + '取到token 但是没有连上xmpp server')
break
default:
alert(err + JSON.stringify(error))
}
} // 登出
logout() {
if (this.connection) {
this.connection.close()
}
} // 发送消息
sendMessage(message, to, config = {
type: 'txt',
success() {
},
fail() {
},
chatType: ''
}) {
const that = this
const id = this.getConnection().getUniqueId()
let ImMessage = this.WebIM.message
const type = config.type
const chatType = config.chatType
let msg = new ImMessage(type, id)
var option = {
msg: message,
to,
roomType: false,
success: (messageId, msgId) => {
let temp = {
id: messageId,
type,
from: that.username,
to,
data: message,
sourceMsg: message,
error: false,
msgId
}
if (config.isGroup) {
temp.groupId = to
} else {
temp.groupId = temp.to
}
temp = that.appendMessage(temp, 'out')
store.dispatch('PUSH_IM_CHART_DIALOG_GROUP_MESSAGE', temp)
config.success()
},
fail: () => {
config.fail()
}
}
if (chatType === 'chatRoom') {
option.chatType = 'chatRoom'
}
option = this._setExt(option)
msg.set(option)
if (chatType === 'chatRoom') {
msg.setGroup('groupchat')
}
this.getConnection().send(msg.body)
} // 添加消息
unShiftMessage(message) {
const className = message.from === this.username ? 'out' : 'in'
console.log(message.from, this.username, className)
const temp = this.appendMessage(message, className)
store.dispatch('UN_SHIFT_IM_CHART_DIALOG_GROUP_MESSAGE', temp)
} // 发送文本消息
sendTextMessage(message, to, success = () => {
}, fail = () => {
}) {
this.sendMessage(message, to, {type: 'txt', success, fail})
} // 发送组消息
sendTextMessageGroup(message, groupId, success) {
this.sendMessage(message, groupId, {type: 'txt', success, chatType: 'chatRoom', isGroup: true})
} // 发送cmd 消息
sendCmdMessage(message, to, success = () => {
}, fail = () => {
}, action = '[CMDMessage]') {
// todo
} /**
* 发送图片
* @param input
* @param to
*/
sendGroupImageMessage(input, to, success = () => {
}, fail = () => {
}, chatType = 'chatRoom') {
const conn = this.getConnection()
const id = conn.getUniqueId() // 生成本地消息id
let ImMessage = this.WebIM.message
const msg = new ImMessage('img', id) // 创建图片消息
// var input = document.getElementById('image') // 选择图片的input
const file = this.WebIM.utils.getFileUrl(input) // 将图片转化为二进制文件
const allowType = {
'jpg': true,
'gif': true,
'png': true,
'bmp': true,
'jpeg': true
}
const that = this
if (file.filetype.toLowerCase() in allowType) {
let option = {
apiUrl: this.config.apiURL,
file: file,
to, // 接收消息对象
roomType: false,
chatType,
onFileUploadError: () => { // 消息上传失败
alert('图片发送失败')
fail()
},
onFileUploadComplete: (file) => { // 消息上传成功
if (Array.isArray(file.entities)) {
for (let v of file.entities) {
let url = file.uri + '/' + v.uuid
let temp = {
id,
type: 'chat',
from: that.username,
to,
url,
error: false,
groupId: to
}
temp = that.appendMessage(temp, 'out')
temp.fileType = 'image'
store.dispatch('PUSH_IM_CHART_DIALOG_GROUP_MESSAGE', temp)
success()
}
}
},
flashUpload: this.WebIM.flashUpload
}
option = this._setExt(option)
msg.set(option)
if (chatType === 'chatRoom') {
msg.setGroup('groupchat')
} else {
msg.body.chatType = chatType
}
conn.send(msg.body)
} else {
alert('只支持:' + allowType.join(',') + '的图片格式')
}
}
} export default Easemob
4. 初始化 登录,获取好友分组以及聊天信息,使用场景系统用户自接登录,所以这里没有单独做注册登录
computed: {// 用户
rosterList () {
return this.GET_IM_CHART_ROSTERLIST || []
},
groupList () {
return this.GET_IM_CHART_GROUPLIST || []
},
// 聊天数据
charts () {
return this.GET_IM_CHART_DIALOG_GROUP_MESSAGE(this.imTo.toId) || []
},
...mapGetters({
GET_IM_CHART_ROSTERLIST: 'GET_IM_CHART_ROSTERLIST',
GET_IM_CHART_GROUPLIST: 'GET_IM_CHART_GROUPLIST',
GET_IM_CHART_DIALOG_GROUP_MESSAGE: 'GET_IM_CHART_DIALOG_GROUP_MESSAGE',
GET_IM_CHART_DIALOG_GROUP_ID: 'GET_IM_CHART_DIALOG_GROUP_ID'
})
},methods: {
initIm () {
// im 登陆
this.im.login('test1', '123456')
},
// 发送消息
sendMessage () {
if (this.imTo.chatType === 'single') {
// 会话
this.im.sendTextMessage(this.txt, this.imTo.toId, () => {
this.txt = ''
})
} else {
// 组
this.im.sendTextMessageGroup(this.txt, this.imTo.toId, () => {
this.txt = ''
})
}
},
// 发送图片消息
sendImageMessage () {
if (!this.imTo.toId) {
alert('发送对象必须')
return
}
this.im.sendGroupImageMessage(this.$refs.imageInput, this.imTo.toId, () => {
this.fileTrigger = !this.fileTrigger
this.$nextTick(_ => {
this.fileTrigger = !this.fileTrigger
})
})
},
toChats (opt) {
if (opt.groupid) {
this.imTo = {
chatType: 'group',
toId: opt.groupid,
toName: opt.groupname
}
} else {
this.imTo = {
chatType: 'single',
toId: opt.name,
toName: opt.name
}
}
},
scrollHandler () {},
// 滚动到底
scrollToBottom () {
this.$nextTick(_ => {
this.$refs['chattingContent'].wrap.scrollTop = this.$refs['chattingContent'].wrap.scrollHeight
})
}
}
git地址:
https://github.com/DarkSide7H/vue-chat
示例截图

vue集成环信IM的更多相关文章
- Vue 集成环信  全局封装环信WebSDK  可直接使用
		2019-11-25更新 npm install --save easemob-websdk请直接使用官方安装方式即可.import WebIM from 'easemob-websdk' 以下是最开 ... 
- iOS:集成环信EaseMobSDK单聊功能
		当然在集成环信之前需要一些准备操作: 1.首先注册环信开发者账号,直接进入环信官网注册即可:http://www.easemob.com 2.按照文档一步一步将需要的文件全部拖入工程中:http:// ... 
- 李洪强iOS开发本人集成环信的经验总结_09_处理好友请求
		李洪强iOS开发本人集成环信的经验总结_09_处理好友请求 实现这种效果: 01 - 遵守处理好友请求的代理协议 02 - 设置代理 03 - 实现代理方法 04 - 实现代理中用到的方法 
- 李洪强iOS开发本人集成环信的经验总结_08_自动登录补充
		李洪强iOS开发本人集成环信的经验总结_08_自动登录补充 来到Appdelegate里面 01 - 遵守自动登录的代理协议 02 - 设置自动登录的代理 03 - 判断与实现 04 - 代理方法的 ... 
- 李洪强iOS开发本人集成环信的经验总结_07_监听好友请求
		李洪强iOS开发本人集成环信的经验总结_07_监听好友请求 来到Appdalegate中: 遵守代理协议 设置代理 实现监听好友请求的回调的方法 
- 李洪强iOS开发本人集成环信的经验总结_06_发送好友请求
		李洪强iOS开发本人集成环信的经验总结_06_发送好友请求 同步好友请求 异步好友请求 
- 李洪强iOS开发本人集成环信的经验总结_03_注册
		李洪强iOS开发本人集成环信的经验总结_03_注册 环信一共提供了三种注册的方法: 01 同步注册: 02 异步注册: 03 - 使用代理回调进行注册,但是3.0没有了,3.0之前有 调用注册 ... 
- 李洪强iOS开发本人集成环信的经验总结_02_基本配置
		李洪强iOS开发本人集成环信的经验总结_02_基本配置 来到APPdelegate中做一些配置 01 - 导入头文件 02 - 在didFinishLaunchingWithOptions用法总结 ... 
- 李洪强iOS开发本人集成环信的经验总结_01环信SDK的导入
		李洪强iOS开发本人集成环信的经验总结_01环信SDK的导入 01 - 直接在项目中导入SDK和一些静态库 这个时候,没有错误的编译没有错误的话,就说明SDK已经配置成功 还有一种方法是用cocoap ... 
随机推荐
- 记录pycharm快捷键出错的其中一个原因
			#pycharm使用小技巧 最近在使用pycharm,所遇到的一些快捷键失效的问题.如ctrl+c,ctrl+v等:包括键入时,总是需要用“i”来实现等问题. 究其缘故,是在安装pycharm时, ... 
- mybatis源码解析之Configuration加载(三)
			概述 上一篇我们主要分析了下<environments>标签下面,transactionManager的配置,上问最后还有个遗留问题:就是在设置事物管理器的时候有个autocommit的变 ... 
- MySQL简单的查询语句
			1.查询特定列:select 列名 from 表名:(必须先进入数据库)或者 select 列名 from 数据库.表名: 2.查询多个列:select 列1,列2,... from 表名: 3.除去 ... 
- Codeforces Round #554 (Div. 2)   C. Neko does Maths  (简单推导)
			题目:http://codeforces.com/contest/1152/problem/C 题意:给你a,b, 你可以找任意一个k 算出a+k,b+k的最小公倍数,让最小公倍数尽量小,求出 ... 
- vue-baidu-map 的简单使用
			首先附上vue-baidu-map 文档地址: https://dafrok.github.io/vue-baidu-map/#/zh/index 1.安装,初步使用,文档说的都很明白,就不在过多重复 ... 
- 对yolo与fasterrcnn    anchors的理解
			yolo: 通过聚类产生5个不同比例的anchors.最后一个特征层的输出(x,y,w,h)与这些不同比列的相乘,将网络层的输出转化为bbox(小尺寸),再通过(H,W)还原成原图大小.一共有5个bb ... 
- 小程序 map组件问题 cover-view问题
			使用小程序的组件map时 在开发者工具上一切顺利 但是在真机预览时 发现地图的层级是最高的 任何标签都覆盖不了它 调整z-index值并没有什么效果 原因是 微信小程序的map.video.canva ... 
- Oracle 的几种循环方式介绍
			1 Oracle 中的Goto 用法: declare x number; begin x:=10; --定义的初始值 <<repeat_loop>> --循环点 x:= x- ... 
- TiDB初步概念
			阅读官方文档画以下路线图: 储存: rockDB用于单机数据固化:完全理解 raft用于分布式数据同步:完全理解 最终对外展示一整个完全有序的Key-Value序列:完全理解 重点:有序,就可以随机访 ... 
- 两种语言实现设计模式(C++和Java)(二:单例模式)
			本篇介绍单例模式,可以说是使用场景最频繁的设计模式了.可以根据实例的生成时间,分为饿汉模式和懒汉模式 懒汉模式:饿了肯定要饥不择食.所以在单例类定义的时候就进行实例化. 饿汉模式:故名思义,不到万不得 ... 
