iOS 群頭像框架 — CDDGroupAvatar

前言:

談到APP里面群頭像功能的實(shí)現(xiàn),很容易想到獲取展示位數(shù)頭像稚茅,并根據(jù)UI繪制圖片纸淮。從開(kāi)發(fā)角度上講,為了更好實(shí)現(xiàn)這個(gè)功能亚享,還需要考慮緩存咽块,占位,以及線程和圖片的繪制欺税。為了可以更優(yōu)雅的實(shí)現(xiàn)這個(gè)功能和減少侵入性侈沪,我設(shè)計(jì)了這個(gè)框架。并希望能讓群頭像的實(shí)現(xiàn)盡可能的能像SDWebImage加載一張圖片那么簡(jiǎn)單晚凿。

接下來(lái)我會(huì)結(jié)合Demo來(lái)談?wù)勥@個(gè)框架的設(shè)計(jì)亭罪。

CDDGroupAvatar框架:

  • 1:使用
  • 2:設(shè)計(jì)初衷
  • 3:實(shí)現(xiàn)分析
  • 4:緩存與更新機(jī)制
  • 5:集成方式
  • 6:不足或后續(xù)優(yōu)化

一.使用

為什么要把使用放在第一個(gè)來(lái)講,因?yàn)槲蚁胝宫F(xiàn)出CDDGroupAvatar的簡(jiǎn)單和方便歼秽,由于功能自身的難度性并不是很大应役,如果封裝出來(lái)的輪子還是很繁瑣,那還不如自己寫(xiě)個(gè)方法類(lèi)來(lái)的輕巧燥筷。

1:調(diào)用

[self.avImageViewW8 dc_setImageAvatarWithGroupId:@"avImageViewW8" Source:_groupNum8];

分類(lèi)方法調(diào)用傳入群頭像id和群頭像數(shù)據(jù)源數(shù)組箩祥,完事!

來(lái)看看展示

groupNum8

2:肆氓?不對(duì)還缺點(diǎn)什么

在CDDGroupAvatar中提供了DCAvatarManager類(lèi)滥比。可以統(tǒng)一設(shè)置做院,baseURL盲泛、頭像類(lèi)型、占位圖等等键耕。這些屬性都或多或少的可以幫助你簡(jiǎn)化調(diào)用寺滚。一般來(lái)說(shuō)加載頭像后臺(tái)返回的數(shù)據(jù)是xxxx.jpg/.png,并不是一個(gè)完整的頭像地址需要我們自行去拼接屈雄,baseUrl屬性就可以很好地處理村视,在初始化的時(shí)候設(shè)置好統(tǒng)一的拼接頭,接下來(lái)你只需這樣酒奶。

// 初始化
[DCAvatarManager sharedAvatar].baseUrl = @"http://xxxxxx";

// 數(shù)組的格式
_groupNum2 = @[@"006tNc79gy1g56or92vvmj30u00u048a.jpg",@"006tNc79gy1g56mcmorgrj30rk0nm0ze.jpg"];

// 加載頭像
baseUrl + _groupNum2[index] 

不用擔(dān)心不同拼接頭的情況蚁孔,頭像本身就是一個(gè)完整的鏈接的話,默認(rèn)就不會(huì)再拼接baseUrl屬性惋嚎。

下面還有一些其他的參數(shù)

#pragma mark - DCAvatarManager屬性

/* 請(qǐng)求的baseURL杠氢。這應(yīng)該只包含URL的共體部分,例如http://www.example.com另伍。 */
@property (strong , nonatomic)NSString *baseUrl;

/* 頭像類(lèi)型枚舉(默認(rèn)微信樣式) */
@property (assign , nonatomic) DCGroupAvatarType groupAvatarType;


/* 頭像背景(默認(rèn)微信背景色)  */
@property (nonatomic, strong) UIColor *avatarBgColor;


/* 一次性設(shè)置小頭像加載失敗的占位圖 : 權(quán)重低于類(lèi)方法中的placeholder屬性 placeholderImage < (id)placeholder  */
@property (nonatomic, strong) UIImage *placeholderImage;


/* 微信和QQ群內(nèi)小頭像間距(默認(rèn)值:2)  */
@property (nonatomic, assign) CGFloat distanceBetweenAvatar;


/* 微博外邊圈寬度(默認(rèn):10)  */
@property (nonatomic, assign) CGFloat bordWidth;


#pragma mark - SDWebImage依賴框架屬性

/* sd加載群內(nèi)單個(gè)小圖片屬性 (默認(rèn):SDWebImageRetryFailed | SDWebImageLowPriority ) */
@property (assign , nonatomic) SDWebImageOptions sdImageOptions;

3:如果你不想設(shè)置統(tǒng)一的占位圖鼻百,例如根據(jù)性別顯示不同占位你也可以這樣

placeholder:占位圖屬性 你可像這樣去傳值@[@"p1",@"p2"] 或者 @[image1,image2] 當(dāng)然@[@"p1",image2]也行。在框架內(nèi)部會(huì)在合適的位置顯示。

// 傳入無(wú)效地址測(cè)試 Placeholder屬性
[self.avImageViewW2 dc_setImageAvatarWithGroupId:@"avImageViewW2" Source:@[@"1",@"2"] itemPlaceholder:@[@"man",@"woman"] options:0 completed:nil];
占位

注温艇!權(quán)重大于 統(tǒng)一設(shè)置的placeholderImage屬性

4:可選和回調(diào)

就像圖片加載框架SDWebImage一樣我同樣提供了加載可選和數(shù)據(jù)的回調(diào)因悲,方便使用者自行選擇。
CDDGroupAvatar提供兩種加載模式DCGroupAvatarCacheType

  • DCGroupAvatarCachedDefault (默認(rèn)) : 走緩存 取到返回 沒(méi)有則獲取最新
  • DCGroupAvatarCachedRefresh : 先讀緩存再獲取最新
[self.avImageViewW4 dc_setImageAvatarWithGroupId:@"avImageViewW4" Source:_groupNum4 itemPlaceholder:@"place" options:DCGroupAvatarCachedRefresh completed:nil];

CDDGroupAvatar提供GroupImageBlock回調(diào):

[self.avImageViewW9 dc_setImageAvatarWithGroupId:@"avImageViewW9" Source:_groupNum9 completed:^(NSString *groupId, UIImage *groupImage, NSArray<UIImage *> *itemImageArray, NSString *cacheId) {
   NSLog(@"groupId:%@ -- 群頭像:%@ 群內(nèi)拼接小頭像數(shù)組:%@ -- cacheId:%@",groupId, groupImage, itemImageArray , cacheId);
}];

5:同樣CDDGroupAvatar也支持Button勺爱,調(diào)用方式和ImageView一樣晃琳,還可以根據(jù)UIControlState屬性去展示。

// Image
[self.avaButton dc_setImageAvatarWithGroupId:@"avaButton" Source:_groupNum9 forState:0];
// Background
[self.avaBgButton dc_setBackgroundImageAvatarWithGroupId:@"avaBgButton" Source:_groupNum4 forState:0];

6:支持什么格式的群頭像

目前CDDGroupAvatar支持三種樣式的群頭像:微信(默認(rèn))琐鲁、QQ蝎土、微博,你可以通過(guò)groupAvatarType去選擇

來(lái)張全家福:

全家福

二:設(shè)計(jì)初衷:

為了減少浸入性绣否,功能內(nèi)聚誊涯,可以使群頭像的實(shí)現(xiàn)盡可能的能像SDWebImage加載一張圖片那么簡(jiǎn)單。同時(shí)更進(jìn)一步的去學(xué)習(xí)SDWebImage的源碼蒜撮。

三:微信樣式分析:

接下來(lái)暴构,我以微信樣式分析一下整個(gè)框架的運(yùn)行流程

image

在如上流程中,主要有圖片的批量下載段磨,尺寸和位置計(jì)算取逾,圖片的繪制,裁剪苹支,緩存和回調(diào)處理砾隅,以及如何優(yōu)雅的兼顧Image和Button的調(diào)用。特別是一開(kāi)始cache為空的時(shí)候批量加載群內(nèi)成員的頭像和完成后回調(diào)债蜜,以及這個(gè)過(guò)程中占位圖和緩存的處理晴埂,還要有一些挑戰(zhàn)的。

從上面最全的一張展示圖來(lái)看寻定,微信和QQ這兩種群頭像圖片的繪制還不算難儒洛,中規(guī)中矩,計(jì)算好小頭像的大小狼速,和位置繪制琅锻。在設(shè)計(jì)過(guò)程中,微博樣式稍微讓我有些頭疼向胡。

1:在拿到群內(nèi)所有成員頭像后恼蓬,首先需要先確定的就是小頭像的尺寸

2:其次是確定每個(gè)頭像所在的位置(x,y)坐標(biāo)

3:根據(jù)他們的frame進(jìn)行群頭像的繪制

4:圖片的屬性處理

為了避免繪制的圖片和地址圖片的屬性不等,我在等圖片繪制成功后會(huì)有一次關(guān)于圖片屬性的調(diào)整僵芹,默認(rèn)以群成員地址加載出來(lái)的屬性為準(zhǔn)处硬。

5:緩存和回調(diào)

在批量加載圖片的的統(tǒng)一回調(diào)中我新增了一個(gè)屬性BOOL succeed,加載的成功性淮捆。用來(lái)判斷是否進(jìn)行存儲(chǔ)郁油。如果群內(nèi)的所有頭像都加載失敗,那就不用存儲(chǔ)了攀痊,直接返回上次的緩存圖片或者默認(rèn)占位圖片桐腌。這樣既可以避免重復(fù)存儲(chǔ),也能一定意義上的優(yōu)化顯示苟径。

四.緩存與更新機(jī)制

說(shuō)到緩存案站,這是在網(wǎng)絡(luò)加載過(guò)程中必不可少的一步,針對(duì)繪制成功的群頭像會(huì)做一次緩存和磁盤(pán)的存儲(chǔ)棘街。緩存方面利用的事 SDWebImage 框架中的Cache蟆盐。既然 SDWebImage 本身的加載就自帶緩存,為什么還需要再做一遍呢遭殉?節(jié)約性能這樣可以避免重復(fù)計(jì)算和繪制石挂。重復(fù)的計(jì)算和繪制都是會(huì)損耗一定的性能。

緩存key是如何定義的险污?又如何能保證及時(shí)更新痹愚?

CDDGroupAvatar 中的cacheId是一段字符屬性的拼接然后進(jìn)行MD5。其中以群頭像id蛔糯,群內(nèi)頭像的數(shù)量(以最大截取數(shù))拯腮,群頭像數(shù)據(jù)源的最后一個(gè)對(duì)象(監(jiān)聽(tīng)變動(dòng)),和一些邊距蚁飒,背景顏色等屬性進(jìn)行拼接动壤。

id%@_num%zd_lastObj%@_distance%.f_bordWidth%.f_bgColor%@

這樣可以在兼顧群內(nèi)成員變動(dòng),主題切換淮逻,甚至自定義邊距改變的同時(shí)能后及時(shí)的對(duì)已經(jīng)繪制的好的緩存中群頭像進(jìn)行更新琼懊。

五.Demo的演示

clean操作:清除所有內(nèi)存緩存和磁盤(pán)緩存

GIF

如上截圖中的樣式在demo演示項(xiàng)目中均有實(shí)現(xiàn)。

六.集成方式

  • CocoaPods

1:在 Podfile 中添加 pod 'CDDGroupAvatar'爬早,執(zhí)行 pod install 或 pod update肩碟。

  • 手動(dòng)導(dǎo)入

1:將demo項(xiàng)目中的 CDDGroupAvatar 文件夾所有內(nèi)容拖入你的工程中。
2:集成 SDWebImage 框架凸椿。

  • 用法

1:導(dǎo)入#import <CDDGroupAvatar/DCAvatar.h>可以擁有全部功能削祈。
2:調(diào)用對(duì)應(yīng)控件的類(lèi)方法。
3:如果有使用上的疑問(wèn)脑漫,可以下載演示demo進(jìn)行查看髓抑。

七.不足或后續(xù)優(yōu)化

1:項(xiàng)目重度依賴SDWebImage框架。不管是圖片的加載和緩存都是用的此框架优幸,為什么不去減少對(duì)外部框架的自己實(shí)現(xiàn)吨拍,成本太高,簡(jiǎn)易的自己去實(shí)現(xiàn)一個(gè)加載圖片和緩存功能网杆,還不見(jiàn)得能比依賴此框架來(lái)的好羹饰。

2:微博類(lèi)型的繪制模式不夠完美伊滋。后續(xù)有需要我會(huì)把此類(lèi)型的實(shí)現(xiàn)拿出來(lái)分析,就目前而言我覺(jué)得現(xiàn)在的處理方式不夠好队秩,有優(yōu)化的空間笑旺。特別是在相交的處理方式上,我更愿意一次繪制的時(shí)候設(shè)置相切路徑馍资。

后續(xù):我重點(diǎn)會(huì)把第二個(gè)優(yōu)化一下筒主。

...

最后還是建議有需要去下載源碼。如果有覺(jué)得處理不當(dāng)?shù)牡胤侥裥罚€望大家能多多指點(diǎn)我乌妙,更好去完善它。

工具:

在設(shè)計(jì)demo和測(cè)試的過(guò)程中用到如下兩款工具:

iPic - Markdown 圖床建钥、文件上傳工具藤韵,一個(gè)很方便的軟件一直在使用,非常推薦熊经,App Store就可以下載還是免費(fèi)的

JPFPSStatus:記錄當(dāng)前屏幕的幀數(shù)(FPS)荠察,joggerplus大神的開(kāi)源,GitHub就有源碼奈搜,集成和使用非常方便悉盆。

參考:

SDWebImage

地址:

博客:CDDGroupAvatar

Github:CDDGroupAvatar

Follow:RocketsChen · GitHub


版本更新 - 1.5.2:

支持脫敏SDWebImage框架,詳情查看

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末馋吗,一起剝皮案震驚了整個(gè)濱河市焕盟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宏粤,老刑警劉巖脚翘,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绍哎,居然都是意外死亡来农,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)崇堰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沃于,“玉大人,你說(shuō)我怎么就攤上這事海诲》庇ǎ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵特幔,是天一觀的道長(zhǎng)咨演。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么卤档? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任瞻凤,我火速辦了婚禮肌幽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缀雳。我一直安慰自己痒玩,他們只是感情好愤估,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布嵌牺。 她就那樣靜靜地躺著打洼,像睡著了一般龄糊。 火紅的嫁衣襯著肌膚如雪逆粹。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天炫惩,我揣著相機(jī)與錄音僻弹,去河邊找鬼。 笑死他嚷,一個(gè)胖子當(dāng)著我的面吹牛蹋绽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播筋蓖,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼卸耘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了粘咖?” 一聲冷哼從身側(cè)響起蚣抗,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瓮下,沒(méi)想到半個(gè)月后翰铡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡讽坏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年锭魔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片路呜。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡迷捧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胀葱,到底是詐尸還是另有隱情党涕,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布巡社,位于F島的核電站膛堤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏晌该。R本人自食惡果不足惜肥荔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一绿渣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧燕耿,春花似錦中符、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蚜锨,卻和暖如春档插,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背亚再。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工郭膛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人氛悬。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓则剃,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親如捅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棍现,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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

  • 小孩子的我在很小的時(shí)候很抗拒長(zhǎng)大。那時(shí)我的印象里镜遣,大人就是金剛己肮,是哆啦A夢(mèng)的口袋,是孫悟空…無(wú)所不能烈涮,無(wú)所不懼朴肺。漸...
    phyllisJ閱讀 197評(píng)論 0 0
  • 我現(xiàn)在也喜歡上不打草稿,直接簽字筆構(gòu)圖了坚洽。 出圖速度很快戈稿,呈現(xiàn)感強(qiáng)。只要抓住主體特征讶舰,簽字筆成圖的速度很快鞍盗,就是速...
    溫迪畫(huà)畫(huà)閱讀 510評(píng)論 4 3