iOS彈幕庫(kù)OCBarrage-如何hold住每秒5000條巨量彈幕

最近公司做新需求, 原來(lái)用的老彈幕庫(kù), 已經(jīng)無(wú)法滿足需要. 迫不得已自己寫了一套彈幕庫(kù)OCBarrage. 這套彈幕庫(kù)輕量, 可拓展, 高度自定義, 超高性能, 簡(jiǎn)單易上手.
無(wú)論哪家公司軟件的性能絕對(duì)是衡量APP好壞的重要指標(biāo). 之前有一次開(kāi)會(huì), 我們領(lǐng)導(dǎo)說(shuō):"我們寫的東西, 有哪些是可以拿的出手阻问,讓我們引以為豪的?". 之前還真就得想一會(huì)兒, 現(xiàn)在可以毫不猶豫的說(shuō)我們的彈幕庫(kù)絕對(duì)是一個(gè)好家伙.
做直播類軟件核心功能一個(gè)是播放器另一個(gè)就是彈幕了. 現(xiàn)在iOS開(kāi)源的彈幕庫(kù)中性能好的不多, 彈幕量稍微大一點(diǎn), 或者彈幕稍微復(fù)雜一點(diǎn), 就會(huì)出現(xiàn)卡頓雅潭,這與它們的底層實(shí)現(xiàn), 設(shè)計(jì)策略以及你的使用方法都有關(guān)系. 關(guān)鍵是動(dòng)畫單一避诽,無(wú)法定制,滿足不了動(dòng)畫的多樣化需求虚倒!OCBarrage正是為解決這些問(wèn)題而生的!
OCBarrage底層使用Core Animation驅(qū)動(dòng), Core Graphics繪圖, GPU渲染, 性能極高, 哪怕是同時(shí)渲染5000條彈幕也不會(huì)感覺(jué)到卡頓. 開(kāi)源地址:https://github.com/w1531724247/OCBarrage
(以下測(cè)試基于iPhone7真機(jī))

同時(shí)渲染2000條彈幕.gif
同時(shí)渲染3000條彈幕.gif
同時(shí)渲染4000條彈幕.gif
同時(shí)渲染5000條彈幕.gif

對(duì)于全民直播這樣的平臺(tái)來(lái)說(shuō),在大主播高峰時(shí)期的彈幕量是很大的钱磅,特別是當(dāng)主播說(shuō)一句:“我們現(xiàn)在開(kāi)始彈幕抽獎(jiǎng)”。彈幕量瞬間就會(huì)漲的很高似枕!所以對(duì)彈幕這一塊的要求還是蠻高的.

性能優(yōu)化原理

彈幕渲染時(shí)比較耗性能的點(diǎn):

  1. 彈幕陰影

主播在戶外直播時(shí)偶爾會(huì)有白色的背景, 而彈幕文字的顏色也是白色的, 這個(gè)時(shí)候彈幕飄到直播畫面的白色區(qū)域會(huì)導(dǎo)致看不到文字內(nèi)容. 為了解決這個(gè)問(wèn)題我們通常會(huì)給彈幕文字添加一個(gè)隱影.以防止這種情況的發(fā)生. 然而別小看這幾個(gè)像素陰影, 它可是性能消耗的大戶. 哪怕是用GPU渲染因?yàn)槭莿?dòng)態(tài)的實(shí)時(shí)的所以也相當(dāng)吃性能. 在實(shí)驗(yàn)的過(guò)程中發(fā)現(xiàn)如果有文字陰影幾十條彈幕就會(huì)出現(xiàn)彈幕卡頓, 結(jié)果就是彈幕抖動(dòng)一跳一跳的.
解決辦法就是用NSAttributeStringNSStrokeColorAttributeName屬性設(shè)置文字的輪廓顏色替換文字陰影.效果對(duì)比如下:

text_shadow.png

text_stroke.png

都能解決我們的問(wèn)題, 但是性能差的可不是一丁半點(diǎn).

  1. 用CALayer替代UIView展示

與UIView相比CALayer更輕量. 性能更好.系統(tǒng)提供的組件為了保證其通用性, 難免有些冗余.這就是我們優(yōu)化的空間.

  1. 彈幕文字下面的漸變色背景

彩色彈幕下面的漸變色背景如果用CAGradientLayer實(shí)現(xiàn)也是比較耗性能的, 但是如果是用圖片呈現(xiàn)的話效果就會(huì)好的多, 但是不夠靈活, 沒(méi)關(guān)系, 我們都一并解決了.

  1. 將內(nèi)容合成一張圖片展現(xiàn)

將所有的內(nèi)容呈現(xiàn)在layer上并布局好位置以后將所有的內(nèi)容合成一張圖片展現(xiàn)在barrageCell的layer上, 并刪除所有的子subview及sublayer, 以提高性能.

效果演示

demonstration.gif
walkBarrage.gif
mixedImageAndText.gif
stopover.gif

使用用法

  • 第一步:

為新的彈幕類型新建一個(gè)數(shù)據(jù)模型 例如:OCBarrageWalkBannerDescriptor. 這個(gè)類必須繼承自OCBarrageDescriptor類.

OCBarrageWalkBannerDescriptor.png

這樣就創(chuàng)建新的彈幕類型的數(shù)據(jù)模型類, 我們可以在這個(gè)類里面添加新的彈幕屬性例如:bannerLeftImageSrc, bannerMiddleColor, bannerRightImageSrc等等.

  • 第二步:

為新的彈幕類型創(chuàng)建建一個(gè)數(shù)據(jù)展示視圖例如:OCBarrageWalkBannerCell. 這個(gè)新的彈幕類型的展示視圖必須繼承自OCBarrageTextCell類.

OCBarrageWalkBannerCell.png

在這個(gè)新的展示視圖里我們可以添加展示相應(yīng)數(shù)據(jù)的子視圖,例如:leftImageView, middleImageView, rightImageView.
并為這個(gè)新的視圖類添加一個(gè)相應(yīng)的數(shù)據(jù)模型類的屬性OCBarrageWalkBannerDescriptor *walkBannerDescriptor來(lái)傳遞數(shù)據(jù).

  • 第三步:
    重寫新視圖OCBarrageWalkBannerCell- (void)setBarrageDescriptor:(OCBarrageDescriptor *)barrageDescriptor方法. 并只能在這個(gè)方法里為walkBannerDescriptor屬性賦值, 在這個(gè)方法里必須要調(diào)用[super setBarrageDescriptor:barrageDescriptor]方法, 不然barrageDescriptor屬性將沒(méi)有值, 并且部分屬性設(shè)置將不生效.OCBarrageCell本身有一個(gè)barrageDescriptor屬性引用數(shù)據(jù)模型. 但是為了方便拓展我們選擇在第二步里為OCBarrageWalkBannerCell添加一個(gè)新的數(shù)據(jù)屬性walkBannerDescriptor. 實(shí)質(zhì)上OCBarrageWalkBannerCellbarrageDescriptor屬性和walkBannerDescriptor指向的是同一個(gè)walkBannerDescriptor對(duì)象.
setBarrageDescriptor.png
  • 第四步:

重寫新視圖OCBarrageWalkBannerCell- (void)updateSubviewsData方法. 渲染引擎在渲染彈幕視圖之前會(huì)自動(dòng)調(diào)用這個(gè)方法. 我們可以在這個(gè)方法里為子視圖設(shè)置數(shù)據(jù)

updateSubviewsData.png

.

  • 第五步:

在第四步設(shè)置好子視圖的數(shù)據(jù)之后就可以計(jì)算并設(shè)置子視圖的大小和位置.重寫- (void)layoutContentSubviews方法, 并在這個(gè)方法里布局子視圖的位置.渲染引擎會(huì)在調(diào)用- (void)updateSubviewsData方法之后自動(dòng)調(diào)用- (void)layoutContentSubviews方法, 這個(gè)方法必須在主線程執(zhí)行.

layoutContentSubviews.png
  • 第六步:

在布局好子視圖的位置之后, 如果想要提高性能可以調(diào)用- (void)convertContentToImage方法, 將可以圖像化的視圖合成一張圖片展示在cell的layer上, 渲染引擎會(huì)在調(diào)用- (void)layoutContentViews方法之后自動(dòng)調(diào)用- (void)convertContentToImage方法, 這個(gè)方法必須在主線程執(zhí)行.

convertContentToImage.png

如果不想將子視圖的內(nèi)容轉(zhuǎn)化成圖片只需重寫- (void)convertContentToImage并留空即可:

convertContentToImage.png
  • 第七步:

如果想要進(jìn)一步優(yōu)化內(nèi)存和性能, 可以重寫- (void)removeSubViewsAndSublayers方法, 刪除之前添加的的subView和sublayer, 并將子視圖置為nil.

removeSubViewsAndSublayers.png

如果既想提高性能, 又有一些無(wú)法圖片化的內(nèi)容(例如:gif)需要展示, 可以重寫- (void)removeSubViewsAndSublayers方法但不調(diào)用[super removeSubViewsAndSublayers]方法, 并選擇性的刪除一些子視圖, 保留一些子視圖.

如果不想刪除子視圖, 只需重寫- (void)removeSubViewsAndSublayers方法并留空即可:

removeSubViewsAndSublayers.png

當(dāng)然寫到這里依然還有優(yōu)化的空間, 后續(xù)會(huì)繼續(xù)優(yōu)化, 歡迎各位仁人志士共同探討指點(diǎn).
開(kāi)源地址:https://github.com/w1531724247/OCBarrage

補(bǔ)充說(shuō)明:
cell會(huì)在動(dòng)畫執(zhí)行完之后調(diào)用- (void)prepareForReuse, 在數(shù)據(jù)設(shè)置并布局完準(zhǔn)備展示的時(shí)候調(diào)用- (void)removeSubViewsAndSublayers, 如果在- (void)removeSubViewsAndSublayers里將子視圖刪除了, 下次重用的時(shí)候要在- (void)prepareForReuse里重新加一下子視圖

想知道實(shí)際效果如何嗎?趕快掃碼下載體驗(yàn)吧!


圖片.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盖淡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凿歼,更是在濱河造成了極大的恐慌褪迟,老刑警劉巖冗恨,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異味赃,居然都是意外死亡派近,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門洁桌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)渴丸,“玉大人,你說(shuō)我怎么就攤上這事另凌∑坠欤” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵吠谢,是天一觀的道長(zhǎng)土童。 經(jīng)常有香客問(wèn)我,道長(zhǎng)工坊,這世上最難降的妖魔是什么献汗? 我笑而不...
    開(kāi)封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮王污,結(jié)果婚禮上罢吃,老公的妹妹穿的比我還像新娘。我一直安慰自己昭齐,他們只是感情好尿招,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著阱驾,像睡著了一般就谜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上里覆,一...
    開(kāi)封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天丧荐,我揣著相機(jī)與錄音,去河邊找鬼喧枷。 笑死虹统,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的割去。 我是一名探鬼主播窟却,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼昼丑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼呻逆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起菩帝,我...
    開(kāi)封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤咖城,失蹤者是張志新(化名)和其女友劉穎茬腿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體宜雀,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡切平,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辐董。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悴品。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖简烘,靈堂內(nèi)的尸體忽然破棺而出苔严,到底是詐尸還是另有隱情,我是刑警寧澤孤澎,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布届氢,位于F島的核電站,受9級(jí)特大地震影響覆旭,放射性物質(zhì)發(fā)生泄漏退子。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一型将、第九天 我趴在偏房一處隱蔽的房頂上張望寂祥。 院中可真熱鬧,春花似錦七兜、人聲如沸壤靶。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贮乳。三九已至,卻和暖如春恬惯,著一層夾襖步出監(jiān)牢的瞬間向拆,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工酪耳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浓恳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓碗暗,卻偏偏與公主長(zhǎng)得像颈将,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子言疗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容