產(chǎn)品定位
定位移動(dòng)社交,并將娛樂(lè)與生活服務(wù)相結(jié)合.
整體架構(gòu)模塊分析
QQ主要分為登錄注冊(cè),消息,聊天,聯(lián)系人,動(dòng)態(tài),側(cè)邊欄,設(shè)置等幾大模塊.其中消息模塊和聊天模塊是核心模塊.好友動(dòng)態(tài)及聯(lián)系人屬于次核心模塊,延續(xù)了PC端的界面結(jié)構(gòu).
整體模塊結(jié)構(gòu)如下圖所示:
整體通過(guò)模塊化設(shè)計(jì),數(shù)據(jù)和UI分離.包含消息,聊天等主要聊天功能的接口封裝為獨(dú)立Target.
通過(guò)長(zhǎng)連接的方式,當(dāng)有消息進(jìn)來(lái)或發(fā)送消息的時(shí)候,進(jìn)行相應(yīng)UI更新.
為增強(qiáng)用戶體驗(yàn),消息,聊天,聯(lián)系人,動(dòng)態(tài),側(cè)邊欄等都采用Native的開(kāi)發(fā)方式,結(jié)合熱更新技術(shù)對(duì)UI進(jìn)行動(dòng)態(tài)調(diào)整.
游戲,會(huì)員,裝扮等個(gè)性化內(nèi)容由于變幻多樣,無(wú)法使用Native的方式"一勞永逸",故采用的是H5的方式.一般H5頁(yè)面會(huì)犧牲部分用戶體驗(yàn),但QQ通過(guò)其強(qiáng)大的服務(wù)端支持,H5頁(yè)面也能達(dá)到原生的流暢效果.
核心模塊分析
登錄注冊(cè)以及主界面消息模塊
登錄問(wèn)題需要考慮到以下幾點(diǎn):
- 被迫下線問(wèn)題:如果在線狀態(tài)下,其他設(shè)備登錄,會(huì)及時(shí)發(fā)送當(dāng)前設(shè)備下線通知,界面通過(guò)UIWindow展示通知Alert,不允許用戶進(jìn)行非登錄操作. 啟動(dòng)App時(shí)會(huì)進(jìn)行免登操作,這時(shí)和后臺(tái)進(jìn)行交互,如果有被擠下線,提示登錄,否則進(jìn)行免登處理.
- 是否允許電腦端和手機(jī)端同時(shí)在線問(wèn)題:后臺(tái)存儲(chǔ)登錄當(dāng)前設(shè)備的信息,比如設(shè)備名稱,型號(hào)等.如果設(shè)置允許電腦手機(jī)同時(shí)在線,后臺(tái)將對(duì)手機(jī)和電腦同時(shí)提供服務(wù)支持,被迫下線問(wèn)題將被區(qū)分單獨(dú)處理.而如果不允許同時(shí)在線,那么被迫下線問(wèn)題會(huì)把電腦,手機(jī)視為一體混同處理.
消息模塊
消息模塊的消息類型繁多復(fù)雜.
消息類型包括普通消息,群消息和系統(tǒng)消息.普通消息僅處理一對(duì)一聊天的情況,群消息處理群聊天情形.系統(tǒng)消息則根據(jù)用戶自定義進(jìn)行個(gè)性化推送.
- 消息類型處理:
邏輯處理放在后臺(tái),客戶端只管拉取數(shù)據(jù).接口給到消息類型,客戶端通過(guò)多個(gè)CellID進(jìn)行不同消息類型處理- 活動(dòng),比如搶紅包:
后臺(tái)發(fā)送搶紅包通知,界面通過(guò)TabeleHeaderView進(jìn)行活動(dòng)展示,并修改下拉刷新功能,下拉刷新不再對(duì)當(dāng)前消息界面進(jìn)行刷新,而是對(duì)圍繞紅包彈幕進(jìn)行功能改造.- 置頂問(wèn)題:
QQ的置頂功能是信息存儲(chǔ)在本地.將置頂?shù)倪@一條數(shù)據(jù)保存到數(shù)據(jù)庫(kù)寥枝,再次請(qǐng)求數(shù)據(jù)時(shí)將數(shù)據(jù)與數(shù)據(jù)庫(kù)的進(jìn)行對(duì)比晒夹,發(fā)現(xiàn)相同的就置頂 .這里應(yīng)對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行模型和功能劃分,使得置頂邏輯清晰易懂,否則后續(xù)涉及到和其他業(yè)務(wù)邏輯的對(duì)撞很容易讓代碼雜亂無(wú)章.
聊天模塊
首先看看聊天中的多種消息類型:
具體如下所示:
聊天界面主要是針對(duì)多種類型消息的UI處理.各種消息類型組成一個(gè)獨(dú)立的代碼模塊,這個(gè)模塊對(duì)每種消息類型提供服務(wù)支持.
語(yǔ)音信息和圖片信息涉及本地緩存,將語(yǔ)音的ID或圖片的名稱以及語(yǔ)音(圖片)內(nèi)容進(jìn)行壓縮處理并分別作為key和value進(jìn)行本地化存儲(chǔ).其他信息進(jìn)行數(shù)據(jù)庫(kù)加密緩存起來(lái).
時(shí)間處理方面,發(fā)送消息時(shí)間通過(guò)毫秒處理,并將發(fā)送時(shí)間一同發(fā)給服務(wù)器,服務(wù)器以發(fā)送的時(shí)間為準(zhǔn)進(jìn)行排序,而不以接收到消息時(shí)間為準(zhǔn).這樣避免多個(gè)消息出現(xiàn)順序錯(cuò)亂的現(xiàn)象.
聊天發(fā)送消息面板功能
這里每個(gè)面板功能都是對(duì)相關(guān)代碼的高度封裝.通過(guò)一個(gè)模塊將這些功能做成"元件",通過(guò)工廠化模式進(jìn)行對(duì)應(yīng)調(diào)用.
-
語(yǔ)音
這里通過(guò)AVFoundation
封裝一個(gè)語(yǔ)音模塊,并添加長(zhǎng)按手勢(shì),對(duì)不同手勢(shì)信息進(jìn)行發(fā)送,取消處理.同時(shí),進(jìn)行語(yǔ)音本地化存儲(chǔ). -
圖片發(fā)送
這里選擇圖片部分使用一個(gè)橫向的UITableView
,并且監(jiān)聽(tīng)系統(tǒng)圖片的變化情況,當(dāng)系統(tǒng)圖片增加時(shí)(比如這個(gè)時(shí)候截圖),對(duì)TableView
進(jìn)行刷新. -
戳一戳
本質(zhì)是動(dòng)態(tài)圖片,當(dāng)發(fā)送后,將動(dòng)態(tài)圖片展示到聊天框中,并相對(duì)應(yīng)展示全屏效果.動(dòng)態(tài)圖片的處理可以使用SDWebImage
里關(guān)于動(dòng)態(tài)圖片的功能,或者自己代碼進(jìn)行實(shí)現(xiàn).
在本地化過(guò)程中,將這些信息通過(guò)key的方式存儲(chǔ)在數(shù)據(jù)庫(kù)中,在展示聊天消息列表的時(shí)候,進(jìn)行替換操作. -
動(dòng)態(tài)圖
動(dòng)態(tài)圖經(jīng)由網(wǎng)絡(luò)在線展示,使用UICollectionView
,使用SDWebImage
對(duì)圖片進(jìn)行下載并展示.發(fā)送時(shí),和戳一戳進(jìn)行類似處理,不過(guò)不會(huì)進(jìn)行全屏效果展示. -
表情
騰訊對(duì)表情的封裝早有見(jiàn)識(shí),他把每個(gè)表情轉(zhuǎn)化成Unicode編碼的形式,在發(fā)送的時(shí)候使用對(duì)應(yīng)編碼發(fā)送.而在展示的時(shí)候,通過(guò)富文本的形式展示.
給一個(gè)表情鍵盤(pán)的例子: YHExpressionKeyBoard
另外,BBS
里也有相關(guān)表情的處理. -
其他功能
這些按鈕控件都對(duì)應(yīng)一個(gè)獨(dú)立功能,此處不再贅述.
對(duì)性能優(yōu)方面的思考
QQ軟件龐大,如果不進(jìn)行新能優(yōu)化,使用體驗(yàn)將大大下降,無(wú)以支撐騰訊龐大的用戶訴求.
- 網(wǎng)絡(luò)請(qǐng)求使用
NSURLSession
,而不是使用NSURLConnection
,使用HTTP 2.0,提高請(qǐng)求速度. -
UITableView
高度提前計(jì)算并做緩存處理,cell
通過(guò)Frame或者FlexBox
方式進(jìn)行設(shè)計(jì),避免使用Masonry
或者NSLayoutConstraint
. - 服務(wù)器傳過(guò)來(lái)的圖片在服務(wù)器端進(jìn)行相關(guān)裁剪處理,避免圖片過(guò)大影響性能.
- 純代碼,不要使用
Xib
或storeBoard
- 用
ARC
管理內(nèi)存 - 重用和延遲加載
views
啟動(dòng)速斷性能優(yōu)化
1.main()
函數(shù)之前的優(yōu)化
- 刪除無(wú)用的類,減少?zèng)]有調(diào)用的
# import
- 減少無(wú)用的
category
- 減少不必要的
Framework
,特別是非系統(tǒng)的 -
check framework設(shè)為
optional和
required仔沿,如果該
framework在當(dāng)前
App支持的所有
iOS系統(tǒng)版本都存在信峻,那么就設(shè)為
required抄囚,否則就設(shè)為
optional洽蛀,因?yàn)?/code>optional`會(huì)有些額外的檢查.
- 刪除無(wú)用的靜態(tài)變量
- 將不必須在+load方法中做的事情延遲到+initialize中
2.main()
函數(shù)之后的優(yōu)化
- 刪除啟動(dòng)時(shí)各業(yè)務(wù)方打的log(因?yàn)槊看斡?code>NSLog方式打印會(huì)隱式的創(chuàng)建一個(gè)
Calendar
) - 梳理應(yīng)用啟動(dòng)時(shí)發(fā)送的所有網(wǎng)絡(luò)請(qǐng)求王污,是否可以統(tǒng)一在異步線程請(qǐng)求
- 不使用
XIB
-
didFinishLaunching
里的非必要代碼進(jìn)行延時(shí)加載或懶加載.