解析YYKit中微博列表的代碼

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

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

Timeline:微博列表
Compose:轉(zhuǎn)發(fā)評(píng)論
Helper:與項(xiàng)目高耦合的工具
API Dump:數(shù)據(jù)源

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

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

很明顯,這個(gè)微博列表用了MVVM模式。WBModel是模塊的基礎(chǔ),這里用YYModel中延展的方法對(duì)接口返回的數(shù)據(jù)重命名和做一些簡(jiǎn)單的修改,一個(gè)WBStatus對(duì)應(yīng)的是一個(gè)cell的數(shù)據(jù)
WBStatusLayout 一個(gè)cell的布局model,在[self _layout]里計(jì)算布局。
[self _layoutTitle]計(jì)算title的布局

這里最重要的一個(gè)技術(shù)點(diǎn)就是把圖片和文字拼在一起,以富文本的形式顯示出來

- (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"; 是一個(gè)占位符
YYTextRunDelegate 包含元素的寬度,行距,間距
設(shè)置CTRunDelegateRef 并用kCTRunDelegateAttributeName標(biāo)記這個(gè)區(qū)段會(huì)有特殊元素混入,ctDelegate不含特殊元素,但是可以通過CTRunDelegateGetRefCon方法反取母體YYTextRunDelegate
WBTextImageViewAttachment 繼承于 YYTextAttachment ,而YYTextAttachment的主要功能是實(shí)現(xiàn)圖片和文字的混排,具體可參考NSTextAttachment
生成NSMutableAttributedString的atr便是圖文富文本了。

[self _layoutProfile]; 計(jì)算名稱頭像欄的布局
[self _layoutPics];計(jì)算引用的圖片文件的布局
[self _layoutTag];計(jì)算tag的布局
[self _layoutToolbar];計(jì)算下發(fā)轉(zhuǎn)發(fā),評(píng)論的toolbar的布局

model是原材料,經(jīng)過加工成有布局?jǐn)?shù)據(jù)的WBStatusLayout,WBStatusCell是顯示的內(nèi)容,現(xiàn)在我們需要把加工好的WBStatusLayout顯示到WBStatusCell,這個(gè)操作就要在WBStatusTimelineViewController里進(jìn)行了

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

UIScrollView會(huì)在有navigation bar時(shí)自動(dòng)下移64位,關(guān)閉這個(gè)屬性,我們可以自己設(shè)置UIScrollView的布局。

數(shù)據(jù)加載
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];
            }
        }
        
        // 復(fù)制一下,讓列表長(zhǎng)一些,不至于滑兩下就到底了
        [_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];
        });
    });

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 由于最近兩個(gè)多月,筆者正和小伙伴們忙于對(duì)公司新項(xiàng)目的開發(fā),筆者主要負(fù)責(zé)項(xiàng)目整體架構(gòu)的搭建以及功能模塊的分工。...
    CoderMikeHe閱讀 27,352評(píng)論 74 270
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,177評(píng)論 4 61
  • 2017.02.22 可以練習(xí),每當(dāng)這個(gè)時(shí)候,腦袋就犯困,我這腦袋真是神奇呀,一說讓你做事情,你就犯困,你可不要太...
    Carden閱讀 1,490評(píng)論 0 1
  • 成功的人永遠(yuǎn)只有20%,因?yàn)槌晒φ叨媚嫘运季S,成功的人懂得舍,成功的人懂得堅(jiān)持,成功的人堅(jiān)信一切的不可能并且愿意...
    世紀(jì)天輝閱讀 290評(píng)論 0 0
  • 九月正式開學(xué)第三周了。聯(lián)考,周練各進(jìn)行了一次,卻幾乎一個(gè)字也沒有總結(jié)。實(shí)在太不應(yīng)該。 昨晚上被一孩子家長(zhǎng)問到最近怎...
    子非魚lily閱讀 238評(píng)論 0 1

友情鏈接更多精彩內(nèi)容