https://github.com/coderMyy/MYCoreTextLabel 圖文混排 , 實現圖片文字混排 , 可顯示常規連接好比網址,@,話題等 , 能夠自定義連接字,設置關鍵字高亮等功能 . 適用於微博,微信,IM聊天對話等場景 . 實現這些功能僅用了幾百行代碼,耦合性也較低java
https://github.com/coderMyy/MYDropMenu 上拉下拉菜單,可隨意自定義,隨意修改大小,位置,各個項目通用git
https://github.com/coderMyy/MYPhotoBrowser 照片瀏覽器。功能主要有 : 點擊點放大縮小 , 長按保存發送給好友操做 , 帶文本描述照片,從點擊照片放大,當前瀏覽照片縮小等功能。功能逐漸完善增長中.github
https://github.com/coderMyy/MYNavigationController 導航控制器的壓縮 , 使得能夠將導航範圍縮小到指定區域 , 實現頁面中的頁面效果 . 適用於路徑選擇,文件選擇等web
#pragma mark - ---------大致思路羅列 /*數據庫
如下思路 , 僅表我的意見 , 且是我能想到比較好的處理方法
=====================================================================================
<<< 大體代碼結構 >>>
GCDSocket
(提供最原始的寫入,讀取,超時等方法)
delegate : ChatHandler單例
怎麼去發送消息,接收消息的實際操做者
||
⏬
ChatHanlder
(做爲中間業務邏輯處理層 , 主要將發送消息,接收消息和各個實際接收的控制器們鏈接起來,數據緩存,處理等)
delegate : 須要接收消息的全部對象 (註冊成爲ChatHandler的代理,ChatHandler中數組對各個對象進行存儲)
數據處理(數據庫以及沙盒),數據緩存(數據庫以及沙盒),消息發送接收業務邏輯處理實際操做者
|| || ||
⏬ ⏬ ⏬
ViewController1 ViewController2 .........
控制器裏須要作的 , 是對內存中消息模型進行操做 , 以此更新UI . 好比進度顯示 , 失敗紅歎號顯示 , 轉圈 , 消息刪除 , 撤回等 ...
這麼設計的好處 :
1. 分工明確 , 每一個控制器獲得的消息 , 都是能夠直接使用的 , 控制器只須要負責主要和V層進行交互 , 避免了在控制器中處理過多的邏輯
2. ChatHandler做爲全局單例 , 生命週期和整個應用保持一致 . 而控制器 , 會隨着用戶操做而銷燬 , 若是把數據放到控制器裏處理 , 極可能會形成數據的丟失
=====================================================================================
<<< 關於緩存結構 >>>
文本/表情消息 語音消息 圖片消息 視頻消息 文件消息 撤回消息 提示語消息
|| || || || || || ||
⏬ ⏬ ⏬ ⏬ ⏬ ⏬ ⏬
數據庫存儲 數據庫存儲 數據庫存儲 數據庫存儲 數據庫存儲 數據庫存儲 數據庫存儲
|| || ||
沙盒緩存(語音data) 沙盒緩存(圖片data) 沙盒緩存(視頻)
===================================================================================
複製代碼
<<<<Socket鏈接>>>>json
登陸 -> 鏈接服務器端口 -> 成功鏈接 -> SSL驗證 -> 發送登陸TCP請求(login) -> 收到服務端返回登陸成功回執(loginReceipt) ->發送心跳 -> 出現鏈接中斷 ->斷網重連3次 -> 退出程序主動斷開鏈接數組
<<<<關於鏈接狀態監聽>>>>瀏覽器
因爲即時通信對於網絡狀態的判斷須要較爲精確 ,原生的Reachability實際上在不少時候判斷並不可靠 。 主要體如今當網絡較差時,程序可能會出現鏈接上網絡 , 但並未實際上可以進行數據傳輸 。 開始嘗試着用Reachability加上一個普通的網絡請求來雙重判斷實現更加精確的網絡監聽 , 可是其實是不可行的 。 若是使用異步請求依然判斷不精確 , 如果同步請求 , 對性能的消耗會很大 。 最終採起的解決辦法 , 使用RealReachability ,對網絡監聽同時 ,PING服務器地址或者百度 ,網絡監聽問題基本上得以解決緩存
TCP的鏈接狀態監聽主要使用服務器和客戶端互相發送心跳 ,彼此驗證對方的鏈接狀態 。 規則能夠本身定義 , 當前使用的規則是 ,當客戶端鏈接上服務器端口後 ,且成功創建SSL驗證後 ,向服務器發送一個登錄的消息(login)。 當收到服務器的登錄成功回執(loginReceipt)開啓心跳定時器 ,每一秒鐘向服務器發送一次心跳 ,心跳的內容以安卓端/iOS端/服務端最終協商後爲準 。 當服務端收到客戶端心跳時,也給服務端發送一次心跳 。正常接收到對方的心跳時,當前鏈接狀態爲已鏈接狀態 ,當服務端或者客戶端超過3次(自定義)沒有收到對方的心跳時,判斷鏈接狀態爲未鏈接。服務器
<<<<關於本地緩存>>>>
建議每一個登錄用戶建立一個DB ,切換用戶時切換DB便可 。 搭建一個完善IM體系 , 每一個DB至少對應3張表 。 一張用戶存儲聊天列表信息,這裏假如它叫chatlist ,即微信首頁 ,用戶存儲每一個羣或者單人會話的最後一條信息 。來消息時更新該表,並更新內存數據源中列表信息。或者每次來消息時更新內存數據源中列表信息 ,退出程序或者退出聊天列表頁時進行數據庫更新。後者避免了頻繁操做數據庫,效率更高。 一張用戶存儲每一個會話中的詳細聊天記錄 ,這裏假如它叫chatinfo。該表也是如此 ,要麼接到消息立馬更新數據庫,要麼先存入內存中,退出程序時進行數據庫緩存。 一張用於存儲好友或者羣列表信息 ,這裏假如它叫myFriends ,每次登錄或者退出,或者修改好友備註,刪除好友,設置星標好友等操做都須要更新該表。
當發送或者接收圖片、語音、文件信息時,須要對信息內容進行沙盒緩存。 沙盒緩存的目錄分層 ,我的建議是在每一個用戶根據本身的userID在Cache中建立文件夾,該文件夾目錄下建立每一個會話的文件夾。 這樣作的好處在於 , 當你須要刪除聊天列表會話或者清空聊天記錄 ,或者app進行內存清理時 ,便於找到該會話的全部緩存。大體的目錄結構以下 ../Cache/userID(當前用戶ID)/toUserID(某個羣或者單聊對象)/...(圖片,語音等緩存)
<<<<關於消息分發>>>>
全局我們設定了一個ChatHandler單例,用於處理TCP的相關邏輯 。那麼當TCP推送過來消息時,我該將這些消息發給誰?誰註冊成爲個人代理,我就發給誰。 ChatHandler單例爲全局的,而且生命週期爲整個app運行期間不會銷燬。在ChatHandler中引用一個數組 ,該數組中存放全部註冊成爲須要收取消息的代理,當每來一條消息時,遍歷該數組,並向全部的代理推送該條消息.
<<<<聊天UI的搭建>>>>
這個頁面沒有太多可說的 , 一個tableView便可搞定 。須要注意的是 ,每次收到消息時,都須要將該消息置頂 。每次進入程序時,拉取chatlist表存儲的每一個會話的最後一條聊天記錄進行展現 。
該頁面tableView或者collectionView都可實現 ,看我的喜愛 。這裏是我用的是tableView . 根據消息類型大體分爲普通消息 ,語音消息 ,圖片消息 ,文件消息 ,視頻消息 ,提示語消息(以上爲打招呼內容,xxx已加入羣,xxx撤回了一條消息等)這幾種 ,固cell的註冊差很少爲5種類型,每種消息對應一種消息。 視頻消息和圖片消息cell能夠複用 。 不建議使用過少的cell類型 ,首先是邏輯太多 ,不便於處理 。其次是效率並不高。
<<<<發送消息>>>>
直接調用我們封裝好的ChatHandler的sendMessage方法便可 , 發送消息時 ,須要存入或者更新chatlist和chatinfo兩張表。如果未鏈接或者發送超時 ,須要從新更新數據庫存儲的發送成功與否狀態 ,同時更新內存數據源 ,刷新該條消息展現便可。 如果表情消息 ,傳輸過程也是以文本的方式傳輸 ,好比一個大笑的表情 ,能夠定義爲[大笑] ,固然規則本身能夠和安卓端web端協商,本地根據plist文件和表情包匹配進行圖文混排展現便可 。 https://github.com/coderMyy/MYCoreTextLabel ,圖文混排地址 , 若是以爲有用 , 請star一下 ,好人一輩子平安
語音消息須要注意的是 ,多和安卓端或者web端溝通 ,找到一個你們均可以接受的格式 ,轉碼時使用同一種格式,避免某些格式其餘端沒法播放,我的建議Mp3格式便可。 同時,語音也須要作相應的降噪 ,壓縮等操做。 發送語音大約有兩種方式 。 一是先對該條語音進行本地緩存 , 而後所有內容均經過TCP傳輸並攜帶該條語音的相關信息,例如時長,大小等信息,具體的你得測試一條壓縮後的語音體積有多大,如果過大,則須要進行分割而後以消息的方法時發送。接收語音時也進行拼接。同時發送或接收時,對chatinfo和chatlist表和內存數據源進行更新 ,超時或者失敗再次更新。 二是先對該條語音進行本地緩存 , 語音內容使用http傳輸,傳輸到服務器生成相應的id ,獲取該id再附帶該條語音的相關信息 ,以TCP方式發送給對方,當對方收到該條消息時,先去下載該條信息,並根據該條語音的相關信息進行展現。同時發送或接收時,對chatinfo和chatlist表和內存數據源進行更新 ,超時或者失敗再次更新。
圖片消息須要注意是 ,經過拍照或者相冊中選擇的圖片應當分紅兩種大小 , 一種是壓縮得很是小的狀態,一種是圖片自己的大小狀態。 聊天頁面展現的 ,僅僅是小圖 ,只有點擊查看時纔去加載大圖。這樣作的目的在於提升發送和接收的效率。 一樣發送圖片也有兩種方式 。 一是先對該圖片進行本地緩存 , 而後所有內容均經過TCP傳輸 ,並攜帶該圖片的相關信息 ,例如圖片的大小 ,名字 ,寬高比等信息 。一樣若是過大也須要進行分割傳輸。同時發送或接收時,對chatinfo和chatlist表和內存數據源進行更新 ,超時或者失敗再次更新。 二是先對該圖片進行本地緩存 , 而後經過http傳輸到服務器 ,成功後發送TCP消息 ,並攜帶相關消息 。接收方根據你該條圖片信息進行UI佈局。同時發送或接收時,對chatinfo和chatlist表和內存數據源進行更新 ,超時或者失敗再次更新。
視頻消息值得注意的是 ,小的視頻沒有太多異議,跟圖片消息的規則差很少 。只是當你從拍照或者相冊中獲取到視頻時,第一時間要獲取到視頻第一幀用於展現 ,而後再發送視頻的內容。大的視頻 ,有個問題就是當你選擇一個視頻時,首先作的是緩存到本地,在那一瞬間 ,可能會出現內存峯值問題 。只要不是過大的視頻 ,如今的手機硬件配置徹底能夠接受的。而上傳採起分段式讀取,這個問題並不會影響太多。
視頻消息我我的建議是走http上傳比較好 ,由於內容通常偏大 。TCP部分僅須要傳輸該視頻封面以及相關信息好比時長,下載地址等相關信息便可。接收方能夠經過視頻大小判斷,若是是小視頻能夠接收到後默認自動下載,自動播放 ,大的視頻則只展現封面,只有當用戶手動點擊時纔去加載。具體的仍是須要根據項目自己的設計而定。
文件方面 ,iOS端並不如安卓端那種可操做性強 ,安卓能夠徹底獲取到用戶裏的全部文件,iOS則有保護機制。一般iOS端發送的文件 ,基本上僅僅侷限於當前app本身緩存的一些文件 ,原理跟發送圖片相似。
撤回消息也是消息內容的一種類型 。例如 A給B發送了一條消息 "你好" ,服務端會對該條消息生成一個messageID ,接收方收到該條消息的messageID和發送方的該條消息messageID一致。若是發送端須要撤回該條消息 ,僅僅須要拿到該條消息messageID ,設置一下消息類型 ,發送給對方 ,當收到撤回消息的成功回執(repealReceipt)時,移除該會話的內存數據源和更新chatinfo和chatlist表 ,並加載提示類型的cell進行展現例如「你撤回了一條消息」便可。接收方收到撤回消息時 ,一樣移除內存數據源 ,並對數據庫進行更新 ,再加載提示類型的cell例如「張三撤回了一條消息」便可。
提示語消息一般來講是服務器作的事情更多 ,除了撤回消息是須要客戶端本身作的事情並很少。 當有人退出羣 ,或者本身被羣主踢掉 ,時服務端推送一條提示語消息類型,並附帶內容,客戶端僅僅須要作展現便可,例如「張三已經加入羣聊」,「以上爲打招呼內容」,「你已被踢出該羣」等。 固然 ,撤回消息也能夠這樣實現 ,這樣提示消息類型邏輯就至關統一,不會顯得很亂 。把主要邏輯交於了服務端來實現。
<<<<消息刪除>>>>
這裏須要注意的一點是 ,相似微信的長按消息操做 ,我採用的是UIMenuController來作的 ,實際上有一點問題 ,就是第一響應者的問題 ,想要展現該menu ,必須將該條消息的cell置爲第一響應者,而後底部的鍵盤失去第一響應者,會降下去 。因此該長按出現menu最好仍是自定義 ,根據計算相對frame進行佈局較好,自定義程度也更好。
消息刪除大概分爲刪除該條消息 ,刪除該會話 ,清空聊天記錄幾種 刪除該條消息僅僅須要移除本地數據源的消息模型 ,更新chatlist和chatinfo表便可。 刪除該會話須要移除chatlist和chatinfo該會話對應的列 ,並根據當前登陸用戶的userID和該會話的toUserID或者groupID移除沙盒中的緩存。 清空聊天記錄,須要更新chatlist表最後一條消息內容 ,刪除chatinfo表,並刪除該會話的沙盒緩存.
<<<<消息拷貝>>>>
這個不用多說 ,一兩句話搞定
<<<<消息轉發>>>>
拿到該條消息的模型 ,並建立新的消息 ,把內容賦值到新消息 ,而後選擇人或者羣發送便可。
值得注意的是 ,若是是轉發圖片或者視頻 ,本地沙盒中的緩存也應當copy一份到轉發對象所對應的沙盒目錄緩存中 ,不能和被轉發消息的會話共用一張圖或者視頻 。由於好比 :A給B發了一張圖 ,A把該圖轉發給了C ,A移除掉A和B的會話 ,那麼若是是共用一張圖的話 ,A和C的會話中就再也沒法找到這張圖進行展現了。
<<<<從新發送>>>>
這個沒有什麼好說的。
<<<<標記已讀>>>>
功能實現比較簡單 ,僅僅須要修改數據源和數據庫的該條會話的未讀數(unreadCount),刷新UI便可。
<<<<如下爲大體的實現步驟>>>>
文本/表情消息 :
方式一: 輸入 ->發送 -> 消息加入聊天數據源 -> 更新數據庫 -> 展現到聊天會話中 -> 調用TCP發送到服務器(若超時,更新聊天數據源,更新數據庫 ,刷新聊天UI) ->收到服務器成功回執(normalReceipt) ->修改數據源該條消息發送狀態(isSend) -> 更新數據庫 方式二: 輸入 ->發送 -> 消息加入聊天數據源 -> 展現到聊天會話中 -> 調用TCP發送到服務器(若超時,更新聊天數據源,刷新聊天UI) ->收到服務器成功回執(normalReceipt) ->修改數據源該條消息發送狀態(isSend) ->退出app或者頁面時 ,更新數據庫
語音消息 :(這裏以http上傳,TCP原理一致)
方式一: 長按錄製 ->壓縮轉格式 -> 緩存到沙盒 -> 更新數據庫->展現到聊天會話中,展現轉圈發送中狀態 -> 調用http分段式上傳(若失敗,刷新UI展現) ->調用TCP發送該語音消息相關信息(若超時,刷新聊天UI) ->收到服務器成功回執 -> 修改數據源該條消息發送狀態(isSend) ->修改數據源該條消息發送狀態(isSend)-> 更新數據庫-> 刷新聊天會話中該條消息UI 方式二: 長按錄製 ->壓縮轉格式 -> 緩存到沙盒 ->展現到聊天會話中,展現轉圈發送中狀態 -> 調用http分段式上傳(若失敗,更新聊天數據源,刷新UI展現) ->調用TCP發送該語音消息相關信息(若超時,更新聊天數據源,刷新聊天UI) ->收到服務器成功回執 -> 修改數據源該條消息發送狀態(isSend -> 刷新聊天會話中該條消息UI - >退出程序或者頁面時進行數據庫更新
圖片消息 :(兩種考慮,一是展現和http上傳均爲同一張圖 ,二是展現使用壓縮更小的圖,http上傳使用選擇的真實圖片,想要作到精緻,方法二更爲可靠)
方式一: 打開相冊選擇圖片 ->獲取圖片相關信息,大小,名稱等,根據用戶是否選擇原圖,考慮是否壓縮 ->緩存到沙盒 -> 更新數據庫 ->展現到聊天會話中,根據上傳顯示進度 ->http分段式上傳(若失敗,更新聊天數據,更新數據庫,刷新聊天UI) ->調用TCP發送該圖片消息相關信息(若超時,更新聊天數據源,更新數據庫,刷新聊天UI)->收到服務器成功回執 -> 修改數據源該條消息發送狀態(isSend) ->更新數據庫 -> 刷新聊天會話中該條消息UI 方式二:打開相冊選擇圖片 ->獲取圖片相關信息,大小,名稱等,根據用戶是否選擇原圖,考慮是否壓縮 ->緩存到沙盒 ->展現到聊天會話中,根據上傳顯示進度 ->http分段式上傳(若失敗,更細聊天數據源 ,刷新聊天UI) ->調用TCP發送該圖片消息相關信息(若超時,更新聊天數據源 ,刷新聊天UI)->收到服務器成功回執 -> 修改數據源該條消息發送狀態(isSend) -> 刷新聊天會話中該條消息UI ->退出程序或者離開頁面更新數據庫
視頻消息:
方式一:打開相冊或者開啓相機錄製 -> 壓縮轉格式 ->獲取視頻相關信息,第一幀圖片,時長,名稱,大小等信息 ->緩存到沙盒 ->更新數據庫 ->第一幀圖展現到聊天會話中,根據上傳顯示進度 ->http分段式上傳(若失敗,更新聊天數據,更新數據庫,刷新聊天UI) ->調用TCP發送該視頻消息相關信息(若超時,更新聊天數據源,更新數據庫,刷新聊天UI)->收到服務器成功回執 -> 修改數據源該條消息發送狀態(isSend) ->更新數據庫 -> 刷新聊天會話中該條消息UI 方式二:打開相冊或者開啓相機錄製 ->壓縮轉格式 ->獲取視頻相關信息,第一幀圖片,時長,名稱,大小等信息 ->緩存到沙盒 ->第一幀圖展現到聊天會話中,根據上傳顯示進度 ->http分段式上傳(若失敗,更細聊天數據源 ,刷新聊天UI) ->調用TCP發送該視頻消息相關信息(若超時,更新聊天數據源 ,刷新聊天UI)->收到服務器成功回執 -> 修改數據源該條消息發送狀態(isSend) -> 刷新聊天會話中該條消息UI ->退出程序或者離開頁面更新數據庫
文件消息: 跟上述一致 ,須要注意的是,若是要實現該功能 ,接收到的文件須要在沙盒中單獨開闢緩存。好比接收到web端或者安卓端的文件
<<<<消息丟失問題>>>>
消息爲何會丟失 ? 最主要緣由應該歸結於服務器對客戶端的網絡判斷不許確。儘管客戶端已經和服務端創建了心跳驗證 , 可是心跳始終是有間隔的,且TCP的鏈接中斷也是有延遲的。例如,在此時我向服務器發送了一次心跳,而後網絡失去了鏈接,或者網絡信號很差。服務器接收到了該心跳 ,服務器認爲客戶端是處於鏈接狀態的,向我推送了某我的向我發送的消息 ,然而此時我卻不能收到消息,因此出現了消息丟失的狀況。
補充: CocoaSyncSocket的三次握手四次揮手驗證,僅僅表如今鏈接時確保可靠的鏈接和斷開 ,而並不能保證消息數據傳輸中的可靠性 , 因此消息數據傳輸,咱們能夠模擬三次握手進行傳輸.
解決辦法 :客戶端向服務端發送消息,服務端會給客戶端返回一個回執,告知該條消息已經發送成功。因此,客戶端有必要在收到消息時,也向服務端發送一個回執,告知服務端成功收到了該條消息。而客戶端,默認收到的全部消息都是離線的,只有收到客戶端的接收消息的成功回執後,纔會移除掉該離線消息緩存,不然將會把該條消息以離線消息方式同步推送。離線消息後面會作解釋。此時的雙向回執,能夠把消息丟失機率降到很是低 ,基本上算是模擬了一個消息數據傳輸的三次握手。
<<<<消息亂序問題>>>>
消息爲何會亂序 ? 客戶端發送消息,該消息會默認賦值當前時間戳 ,收到安卓端或者web端發來的消息時,該時間戳是安卓和web端獲取,這樣就可能會出現時間戳的偏差狀況。好比當前聊天展現順序並無什麼問題,由於展現是收到一條展現一條。可是當退出頁面從新進入時,若是拉取數據庫是根據時間戳的降序拉取 ,那麼就很容易出現混亂。 解決辦法 :表結構設置自增ID ,消息的順序展現以入庫順序爲準 ,拉取數據庫獲取消息記錄時,根據自增ID降序拉取 。這樣就解決了亂序問題 ,至少保證了,展現的消息順序和我聊天時的同樣。儘管時間戳可能並不同是按照嚴謹的降序排列的。
<<<<離線消息>>>> 進入後臺,接收消息提醒: 解決方式要麼採用極光推送進行解決 ,要麼讓本身服務器接蘋果的服務器也行。畢竟極光只是做爲一箇中間者,最終都是經過蘋果服務器推送到每一個手機。
進入程序加載離線消息:此處須要注意的是,若服務器僅僅是把每條消息逐個推送過來,那麼客戶端會出現一些小問題,好比角標數爲每次增長1,最後一條消息不斷更新 ,直到離線消息接收到完畢,形成一種很差的體驗。 解決辦法:離線消息服務端所有進行拼接或者以jsonArray方式,並協議分割方式,客戶端收到後僅需僅需切割,直接在角標上進行總數的相加,並直接更新最後一條消息便可。亦或者,設置包頭信息,告知每條消息長度,切割方式等。
<<<<版本兼容性問題處理>>>> 其實 , 作IM遇到最麻煩的問題之一 , 就應當是版本兼容問題 . 即時通信的功能點有不少 , 項目不可能一期全部的功能所有作完 , 那麼就會涉及到新老版本兼容的問題 . 固然若是服務端經驗足夠豐富 , 版本兼容的問題能夠交於服務端來完成 , 客戶端並不須要作太多額外的事情 . 若是是並行開發 , 服務端思路不夠長遠 ,或者產品需求變動頻繁且比較大.那麼客戶端也須要作一些相應的版本兼容問題 . 處理版本兼容問題並不難 , 主要問題在於當增長一個新功能時 , 服務端或許會推送過來更多的字段 , 而老版本的項目數據庫若是沒有預留足夠的字段 , 就涉及到了數據庫升級 . 而當收到高版本新功能的消息時 , 客戶端也應當對該消息作相應的處理 . 例如,老版本的app不支持消息撤回 , 而新版本支持消息撤回 , 當新版本發送消息撤回時 , 老版本能夠攔截到這條未知的消息類型 , 作相應的處理 , 好比替換成一條提示"該版本暫不支持,請前往appstore下載新版本"等. 而當必要時 , 若是整個IM結構沒有通過深思熟慮 , 還可能會涉及到強制升級 .
<<<<[有人@你]>>>> 對於 有人@你 這個功能的實現可分爲2部分 :
聊天列表最後一條消息前展現[有人@你] ,例如 [有人@你]你好 . 由於有人@你這個功能只出如今羣組中 ,因此在發送消息時 ,設立"toUser"字段便可,固然這個字段名能夠本身設定,當發送端@多我的時,本身定義規則進行拼接(安卓端,iOS端,web端協商),例如@"userID1,userID2,userID3"則代表了我@了這三我的. 當接收端接收到toUser字段不爲空時,切割遍歷userID是否有本身的id便可.若是有,說明有人@我 ,偏好設置userdefault進行存儲狀態便可 .進入該條會話,清除userdefault .
聊天對話頁的錨點展現 , 具體何時展現錨點,微信的邏輯大概是: 當一個羣處於正常狀態下,有人@我 ,右上角展現 "有人@我"按鈕,點擊按鈕拉取全部的未讀消息,這裏是未讀消息,而不是定位到"有人@我"那一條 . 若沒有人@我,則展現"未讀消息"按鈕 , 定位也是到第一條未讀消息位置
當一個羣處於免打擾狀態下,有人@我,右上角展現"有人@你"按鈕 , 點擊按鈕 ,定位到 "有人@我"那一條.
這裏個人作法是 , 直接拉取數據庫從 "有人@你" 或者全部的未讀消息到最新的一條消息間的全部消息, 這樣作法對於用戶量不是特別大的狀況下 , 不會出現任何問題.如果消息數量特別龐大 , 幾千甚至上萬條 ,該作法就不適用了,拉取的數據過多,解決辦法能夠借鑑微信作法 , 定位時獲取中間一段消息,而後進行上拉或者下拉再去相似分頁的去拉取數據庫.
<<<<[草稿]功能>>>> 草稿功能相對簡單 ,跟 "有人@你" 展現邏輯差很少 , 當退出聊天會話頁時,檢查一下鍵盤輸入框中是否有值 , 有值則userdefault存入該信息和對應的該條會話的userID或者groupID.聊天頁面展現時,判斷一下該條會話是否有草稿,若是有展現 . 進入聊天會話頁時,也檢查一次是否有草稿 ,若是有,自動彈起鍵盤,填充上次的內容便可.
<<<<注意事項>>>>
以上僅爲大致的思路 , 實際上搭建IM , 更多的難點在於邏輯的處理和各類細節問題 . 好比數據庫,本地緩存,和服務端的通訊協議,和安卓端私下通訊協議.以及聊天UI的細節處理,例如聊天背景實時拉高,圖文混排等等一系列麻煩的事.沒辦法寫到很詳細 ,都須要本身仔細的去思考.難度並不算很大,只是比較費心.
寫在最後 :
其實上述的思路什麼的 , 也許看的時候並不以爲複雜 , 可是實際上真正去搭建時 , 其中遇到的各類問題仍是很是的噁心 ,直到功能所有作完 ,纔對總體有了一個比較全面的認識 . 還有就是不少人在求UI方面的代碼 , 因爲最近一直在抽時間學習java方面的東西 , UI的東西我會盡快的補上來 ,UI不難 ,難的是UI串起來的邏輯和細節 ...
https://github.com/coderMyy/CocoaAsyncSocket_Demo github地址 ,會持續更新關於即時通信的細節 , 以及最終的UI代碼