解析YYKit中微博列表的代碼

YYKit是ibireme大神寫的一個集model(JSON模型轉換)、cache(緩存)、image(圖片處理)、text(富文本)等 于一身的優秀第三方開源框架,YYKit的強大是被大多數iOS程序員公認的。直接講解框架的源代碼有些枯燥,那我們就根據demo中的微博的例子來解析一下YYKit的實際用法。

首先看看微博分成哪些模塊
1B6EA894-2C75-4FF5-9694-5A6E6B7892BB.png

Timeline:微博列表
Compose:轉發評論
Helper:與項目高耦合的工具
API Dump:數據源

Timeline是這里面最核心的模塊了,我們就來解析一下Timeline的代碼

我們本著由淺入深的原則,在解析WBStatusTimelineViewController類之前,先看看其他幾個類的內容
WBStatusLayout:cell的布局model
WBStatusCell:微博列表的cell
WBModel:數據model

很明顯,這個微博列表用了MVVM模式。WBModel是模塊的基礎,這里用YYModel中延展的方法對接口返回的數據重命名和做一些簡單的修改,一個WBStatus對應的是一個cell的數據
WBStatusLayout 一個cell的布局model,在[self _layout]里計算布局。
[self _layoutTitle]計算title的布局

這里最重要的一個技術點就是把圖片和文字拼在一起,以富文本的形式顯示出來

- (NSAttributedString *)_attachmentWithFontSize:(CGFloat)fontSize imageURL:(NSString *)imageURL shrink:(BOOL)shrink {
    /*
     微博 URL 嵌入的圖片,比臨近的字體要小一圈。。
     這里模擬一下 Heiti SC 字體,然后把圖片縮小一下。
     */
    CGFloat ascent = fontSize * 0.86;
    CGFloat descent = fontSize * 0.14;
    CGRect bounding = CGRectMake(0, -0.14 * fontSize, fontSize, fontSize);
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(ascent - (bounding.size.height + bounding.origin.y), 0, descent + bounding.origin.y, 0);
    CGSize size = CGSizeMake(fontSize, fontSize);
    
    if (shrink) {
        // 縮小~
        CGFloat scale = 1 / 10.0;
        contentInsets.top += fontSize * scale;
        contentInsets.bottom += fontSize * scale;
        contentInsets.left += fontSize * scale;
        contentInsets.right += fontSize * scale;
        contentInsets = UIEdgeInsetPixelFloor(contentInsets);
        size = CGSizeMake(fontSize - fontSize * scale * 2, fontSize - fontSize * scale * 2);
        size = CGSizePixelRound(size);
    }
    
    YYTextRunDelegate *delegate = [YYTextRunDelegate new];
    delegate.ascent = ascent;
    delegate.descent = descent;
    delegate.width = bounding.size.width;
    
    WBTextImageViewAttachment *attachment = [WBTextImageViewAttachment new];
    attachment.contentMode = UIViewContentModeScaleAspectFit;
    attachment.contentInsets = contentInsets;
    attachment.size = size;
    attachment.imageURL = [WBStatusHelper defaultURLForImageURL:imageURL];
    
    NSMutableAttributedString *atr = [[NSMutableAttributedString alloc] initWithString:YYTextAttachmentToken];
    [atr setTextAttachment:attachment range:NSMakeRange(0, atr.length)];
    CTRunDelegateRef ctDelegate = delegate.CTRunDelegate;
    [atr setRunDelegate:ctDelegate range:NSMakeRange(0, atr.length)];
    if (ctDelegate) CFRelease(ctDelegate);
    
    return atr;
}

YYTextAttachmentToken = @"\uFFFC"; 是一個占位符
YYTextRunDelegate 包含元素的寬度,行距,間距
設置CTRunDelegateRef 并用kCTRunDelegateAttributeName標記這個區段會有特殊元素混入,ctDelegate不含特殊元素,但是可以通過CTRunDelegateGetRefCon方法反取母體YYTextRunDelegate
WBTextImageViewAttachment 繼承于 YYTextAttachment ,而YYTextAttachment的主要功能是實現圖片和文字的混排,具體可參考NSTextAttachment
生成NSMutableAttributedString的atr便是圖文富文本了。

[self _layoutProfile]; 計算名稱頭像欄的布局
[self _layoutPics];計算引用的圖片文件的布局
[self _layoutTag];計算tag的布局
[self _layoutToolbar];計算下發轉發,評論的toolbar的布局

model是原材料,經過加工成有布局數據的WBStatusLayout,WBStatusCell是顯示的內容,現在我們需要把加工好的WBStatusLayout顯示到WBStatusCell,這個操作就要在WBStatusTimelineViewController里進行了

if ([self respondsToSelector:@selector( setAutomaticallyAdjustsScrollViewInsets:)]) {
        self.automaticallyAdjustsScrollViewInsets = NO;
    }

UIScrollView會在有navigation bar時自動下移64位,關閉這個屬性,我們可以自己設置UIScrollView的布局。

數據加載
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i = 0; i <= 7; i++) {
            NSData *data = [NSData dataNamed:[NSString stringWithFormat:@"weibo_%d.json",i]];
            WBTimelineItem *item = [WBTimelineItem modelWithJSON:data];
            for (WBStatus *status in item.statuses) {
                WBStatusLayout *layout = [[WBStatusLayout alloc] initWithStatus:status style:WBLayoutStyleTimeline];
//                [layout layout];
                [_layouts addObject:layout];
            }
        }
        
        // 復制一下,讓列表長一些,不至于滑兩下就到底了
        [_layouts addObjectsFromArray:_layouts];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            self.title = [NSString stringWithFormat:@"Weibo (loaded:%d)", (int)_layouts.count];
            [indicator removeFromSuperview];
            self.navigationController.view.userInteractionEnabled = YES;
            [_tableView reloadData];
        });
    });

開啟后臺線程:
NSData *data = [NSData dataNamed:[NSString stringWithFormat:@"weibo_%d.json",i]]; json格式的數據源
WBTimelineItem *item = [WBTimelineItem modelWithJSON:data]; 轉成model
WBStatusLayout *layout = [[WBStatusLayout alloc] initWithStatus:status style:WBLayoutStyleTimeline]; model轉成cell的布局VM
回到主線程開始布局。
整個微博列表WBStatusTimelineViewController不過三百多行,繁雜的布局和數據處理工作都交給WBStatusLayout了,控制器只需要處理一下頁面的邏輯,這樣的項目可讀性高,耦合度低,方便別人也方便自己。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容

  • 前言 由于最近兩個多月,筆者正和小伙伴們忙于對公司新項目的開發,筆者主要負責項目整體架構的搭建以及功能模塊的分工。...
    CoderMikeHe閱讀 27,063評論 74 271
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,151評論 4 61
  • 2017.02.22 可以練習,每當這個時候,腦袋就犯困,我這腦袋真是神奇呀,一說讓你做事情,你就犯困,你可不要太...
    Carden閱讀 1,363評論 0 1
  • 成功的人永遠只有20%,因為成功者懂得逆性思維,成功的人懂得舍,成功的人懂得堅持,成功的人堅信一切的不可能并且愿意...
    世紀天輝閱讀 256評論 0 0
  • 九月正式開學第三周了。聯考,周練各進行了一次,卻幾乎一個字也沒有總結。實在太不應該。 昨晚上被一孩子家長問到最近怎...
    子非魚lily閱讀 216評論 0 1