AsyncDisplayKit的使用

AsyncDisplayKit的使用


一、簡介

AsyncDisplayKit 是一個UI框架同欠,最初誕生于 Facebook 的 Paper 應(yīng)用程序镀首。它是為了解決 Paper 團(tuán)隊面臨的核心問題之一:盡可能緩解主線程的壓力。它能在異步線程繪制修改UI碳蛋,然后統(tǒng)一添加進(jìn)內(nèi)存渲染出來钧忽。

image

ASDK 的作者是 Scott Goodson (Linkedin)毯炮,
他曾經(jīng)在蘋果工作,負(fù)責(zé) iOS 的一些內(nèi)置應(yīng)用的開發(fā)耸黑,比如股票桃煎、計算器、地圖大刊、鐘表为迈、設(shè)置三椿、Safari 等,當(dāng)然他也參與了 UIKit framework 的開發(fā)葫辐。后來他加入 Facebook 后搜锰,負(fù)責(zé) Paper 的開發(fā),創(chuàng)建并開源了 AsyncDisplayKit耿战。目前他在 Pinterest 和 Instagram 負(fù)責(zé) iOS 開發(fā)和用戶體驗的提升等工作蛋叼。

1.解決的問題

很多時候用戶在操作app的時候,會感覺到不適那么流暢剂陡,有所卡頓狈涮。
ASDK主要就是解決的問題就是操作頁面過程中的保持幀率在60fps(理想狀態(tài)下)的問題。

造成卡頓的原因有很多鸭栖,總結(jié)一句話基本上就是:
CPU或GPU消耗過大歌馍,導(dǎo)致在一次同步信號之間沒有準(zhǔn)備完成,沒有內(nèi)容提交晕鹊,導(dǎo)致掉幀的問題松却。
具體的原理,在提升 iOS 界面的渲染性能文章中介紹的十分詳細(xì)了溅话,這里也不多闡述了晓锻。

2.優(yōu)化原理

  • 布局:
    iOS自帶的Autolayout在布局性能上存在瓶頸,并且只能在主線程進(jìn)行計算公荧。(參考Auto Layout Performance on iOS)因此ASDK棄用了Autolayout带射,自己參考自家的ComponentKit設(shè)計了一套布局方式。
  • 渲染
    對于大量文本循狰,圖片等的渲染窟社,UIKit組件只能在主線程并且可能會造成GPU繪制的資源緊張。ASDK使用了一些方法绪钥,比如圖層的預(yù)混合等灿里,并且異步的在后臺繪制圖層,不阻塞主線程的運行程腹。
  • 系統(tǒng)對象創(chuàng)建與銷毀
    UIKit組件封裝了CALayer圖層的對象匣吊,在創(chuàng)建、調(diào)整寸潦、銷毀的時候色鸳,都會在主線程消耗資源。ASDK自己設(shè)計了一套Node機(jī)制见转,也能夠調(diào)用命雀。

實際上,從上面的一些解釋也可以看出斩箫,ASDK最大的特點就是"異步"吏砂。
將消耗時間的渲染撵儿、圖片解碼、布局以及其它 UI 操作等等全部移出主線程狐血,這樣主線程就可以對用戶的操作及時做出反應(yīng)淀歇,來達(dá)到流暢運行的目的。

ASDK 認(rèn)為匈织,阻塞主線程的任務(wù)浪默,主要分為上面這三大類。

為了盡量優(yōu)化性能报亩,ASDK 嘗試對 UIKit 組件進(jìn)行封裝:

3.Nodes節(jié)點

  • 如果你之前使用過views浴鸿,那么你應(yīng)該已經(jīng)知道如何使用nodes井氢,大部分的方法都有一個等效的node弦追,大部分的UIView和CALayer的屬性都有類似的可用的。任何情況都會有一點點命名差異(例如花竞,clipsToBounds和masksToBounds)劲件,node基本上都是默認(rèn)使用UIView的名字,唯一的例外是node使用position而不是center

  • 當(dāng)然约急,你也可以直接訪問底層view和layer零远,使用node.view和node.layer

  • 關(guān)系圖


    image

    這是常見的 UIView 和 CALayer 的關(guān)系:View 持有 Layer 用于顯示,View 響應(yīng)觸摸事件厌蔽。

關(guān)系圖

不需要響應(yīng)觸摸事件
  • Node控件
ASDK UIKit
ASDisplayNode UIView
ASCellNode UITableViewCell/UICollectionViewCell
ASTextNode UILabel
ASImageNode/ASNetworkImageNode UIImageView
ASVideoNode AVPlayerLayer
ASControlNode UIControl
ASScrollNode UIScrollView
ASEditableTextNode UITextView
ASMultiplexImageNode(圖片管理) UIImageView

4.安裝

CocoaPods安裝

pod 'AsyncDisplayKit'

Carthage安裝

AsyncDisplayKit可以使用Carthage安裝牵辣,將下面的代碼添加進(jìn)入Cartfile

github "facebook/AsyncDisplayKit"

在終端執(zhí)行carthage update來構(gòu)建AsyncDisplayKit庫,會自動在項目根目錄下生成Carthage名字的文件夾奴饮,里面有個build文件夾纬向,可以用來framework到你打算使用的項目中

靜態(tài)庫

AsyncDisplayKit可以當(dāng)做靜態(tài)庫引入

  • 拷貝整個工程到你的目錄下,添加AsyncDisplayKit.xcodeproj到你的workspace
  • 在build phases中戴卜,在Target Dependencies下添加AsyncDisplayKit Library
  • 在build phases中逾条,添加libAsyncDisplayKit.a, AssetsLibrary, Photos等框架到Link Binary With Libraries中
  • 在build settings中,添加-lc++和-ObjC到 project linker flags

二投剥、使用

主要介紹常用控件ASTableNode/ASCollectionNode的使用师脂,代碼放在GitHub上的ASDK_Demo

1.ASImageNode

  • 使用ASNetworkImageNode的URL設(shè)置網(wǎng)絡(luò)圖片江锨。
  • ASNetworkImageNode有圖片下載的ASNetworkImageNodeDelegate
  • ASImageNode使用ASDK的圖片管理類PINCache,PINRemoteImage
  • 如果不打算引入PINRemoteImage和PINCache吃警,你會失去對jpeg的更好的支持,你需要自行引入你自己的cache系統(tǒng)啄育,需要遵從ASImageCacheProtocol

2.ASTextNode

ASTextNode沒有text屬性酌心,只能使用attributedText

//居中
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentCenter;
        
labelNode.attributedText = [[NSAttributedString alloc] initWithString:@"居中文字" attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:18],
                                                                                                      NSForegroundColorAttributeName:[UIColor blackColor],
                                                                                                      NSBackgroundColorAttributeName : [UIColor clearColor],
                                                                                                      NSParagraphStyleAttributeName:paragraphStyle}];

3.ASTableNode/ASCollectionNode

  • ASTableNode/ASCollectionNode不支持復(fù)用機(jī)制,每次滾動都會重新創(chuàng)建cell灸撰。
  • ASTableNode并不提供類似UITableview的-tableView:heightForRowAtIndexPath:方法谒府,這是因為節(jié)點基于自己的約束來確定自己的高度拼坎,就是說你不再需要寫代碼來確定這個細(xì)節(jié),一個node通過-layoutSpecThatFits:方法返回的布局規(guī)則確定了行高完疫,所有的節(jié)點只要提供了約束大小泰鸡,就有能力自己確定自己的尺寸
  • 使用 Batch Fetching 進(jìn)行無限滾動,即預(yù)加載功能

三壳鹤、布局

引用1
引用2

ASDK 擁有自己的一套成熟布局方案盛龄,雖然學(xué)習(xí)成本略高,但至少比原生的 AutoLayout 寫起來舒服芳誓,重點是性能比起 AutoLayout 好的不是一點點余舶。(ASDK不支持autoLayout)

//下面這個方法就是用來建立布局規(guī)則對象,產(chǎn)生 node 大小以及所有子 node 大小的地方锹淌,你創(chuàng)建的布局規(guī)則對象一直持續(xù)到這個方法返回的時間點匿值,經(jīng)過了這個時間點后,它就不可變了赂摆。尤其重要要記住的一點事挟憔,千萬不要緩存布局規(guī)則對象,當(dāng)你以后需要他的時候烟号,請重新創(chuàng)建绊谭。
//調(diào)用時機(jī):ASDisplayNode 在初始化之后會檢查是否有子視圖,如果有就會調(diào)用
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize 

1. 布局類

  • ASAbsoluteLayoutSpec(絕對布局約束)
  • ASBackgroundLayoutSpec(背景布局規(guī)則)
  • ASInsetLayoutSpec(邊距布局規(guī)則)
  • ASOverlayLayoutSpec(覆蓋布局規(guī)則)
  • ASRatioLayoutSpec(比例布局規(guī)則)
  • ASRelativeLayoutSpec(相對布局規(guī)則)
  • ASCenterLayoutSpec(中心布局規(guī)則)
  • ASStackLayoutSpec(堆疊布局規(guī)則)
  • ASWrapperLayoutSpec (填充布局規(guī)則)

2.示例

ASAbsoluteLayoutSpec

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{
  self.childNode.style.layoutPosition = CGPointMake(100, 100);
  self.childNode.style.preferredLayoutSize = ASLayoutSizeMake(ASDimensionMake(100), ASDimensionMake(100));

  ASAbsoluteLayoutSpec *absoluteLayout = [ASAbsoluteLayoutSpec absoluteLayoutSpecWithChildren:@[self.childNode]];
  return absoluteLayout;
}

使用方法和原生的絕對布局類似

ASBackgroundLayoutSpec

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{
  ASBackgroundLayoutSpec *backgroundLayout = [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild:self.childNodeB background:self.childNodeA];
  return backgroundLayout;
}

把childNodeA 做為 childNodeB 的背景汪拥,也就是 childNodeB 在上層达传,要注意的是 ASBackgroundLayoutSpec 事實上根本不會改變視圖的層級關(guān)系

ASInsetLayoutSpec

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{
    ASInsetLayoutSpec *inset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsZero child:_childNode];
    return insetLayout;
}

_childNode 相對于父視圖邊距都為 0,相當(dāng)于填充整個父視圖迫筑。

ASOverlayLayoutSpec

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{

  _photoNode.style.preferredSize = CGSizeMake(USER_IMAGE_HEIGHT*2, USER_IMAGE_HEIGHT*2);

  // INIFINITY(插入無邊界)
  UIEdgeInsets insets = UIEdgeInsetsMake(INFINITY, 12, 12, 12);
  ASInsetLayoutSpec *textInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:_titleNode];

  return [ASOverlayLayoutSpec overlayLayoutSpecWithChild:_photoNode 
                                                 overlay:textInsetSpec];

}

類似于ASBackgroundLayoutSpec宪赶,都是設(shè)置層級關(guān)系

ASRatioLayoutSpec

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{
    ASRatioLayoutSpec *ratioLayout = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.0f child:self.childNodeA];
    return ratioLayout;
}

比較常用的一個類,作用是設(shè)置自身的高寬比铣焊,例如設(shè)置正方形的視圖

ASRelativeLayoutSpec

image
//把 childNodeA 顯示在右上角逊朽。
    self.childNodeA.style.preferredSize = CGSizeMake(100, 100);
    ASRelativeLayoutSpec *relativeLayout = [ASRelativeLayoutSpec relativePositionLayoutSpecWithHorizontalPosition:ASRelativeLayoutSpecPositionEnd verticalPosition:ASRelativeLayoutSpecPositionStart sizingOption:ASRelativeLayoutSpecSizingOptionDefault child:self.childNodeA];
    return relativeLayout;
}

它可以把視圖布局在:左上、左下曲伊、右上叽讳、右下四個頂點以外,還可以設(shè)置成居中布局坟募。

ASCenterLayoutSpec

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{
    self.childNodeA.style.preferredSize = CGSizeMake(100, 100);
    ASCenterLayoutSpec *relativeLayout = [ASCenterLayoutSpec centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringXY sizingOptions:ASCenterLayoutSpecSizingOptionDefault child:self.childNodeA];
    return relativeLayout;
}

ASWrapperLayoutSpec

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{    
    ASWrapperLayoutSpec *wrapperLayout = [ASWrapperLayoutSpec wrapperWithLayoutElement:self.childNodeA];
    return wrapperLayout;
}

填充整個視圖

ASStackLayoutSpec

可以說這是最常用的類岛蚤,而且相對于其他類來說在功能上是最接近于 AutoLayout 的。
之所以稱之為盒子布局是因為它和 CSS 中 Flexbox 很相似懈糯,不清楚 Flexbox 的可以看下這篇博客(HTML布局)涤妒。

示例

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize{

  // 當(dāng)用戶名和位置信息文本太長時,收縮堆放視圖來適應(yīng)屏幕,而不是將所有內(nèi)容向右堆放
  ASStackLayoutSpec *nameLocationStack = [ASStackLayoutSpec verticalStackLayoutSpec];
  nameLocationStack.style.flexShrink = 1.0;
  nameLocationStack.style.flexGrow = 1.0;

  //如果從服務(wù)器獲取位置信息,并檢查位置信息是否可用
  if (_postLocationNode.attributedText) {
    nameLocationStack.children = @[_usernameNode, _postLocationNode];
  } else {
    nameLocationStack.children = @[_usernameNode];
  }

  //水平堆放
  ASStackLayoutSpec *headerStackSpec = [ASStackLayoutSpec   stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal
                     spacing:40     
              justifyContent:ASStackLayoutJustifyContentStart
                  alignItems:ASStackLayoutAlignItemsCenter
                    children:@[nameLocationStack, _postTimeNode]];

  //插入堆放
  return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(0, 10, 0, 10)    
                                                child:headerStackSpec];

}

簡單的說明下各個參數(shù)的作用:
1.direction:主軸的方向,有兩個可選值:

  • 縱向:ASStackLayoutDirectionVertical(默認(rèn))
  • 橫向:ASStackLayoutDirectionHorizontal
    2.spacing: 主軸上視圖排列的間距赚哗,比如有四個視圖她紫,那么它們之間的存在三個間距值都應(yīng)該是spacing
    3.justifyContent: 主軸上的排列方式硅堆,有五個可選值:
  • ASStackLayoutJustifyContentStart 從前往后排列
  • ASStackLayoutJustifyContentCenter 居中排列
  • ASStackLayoutJustifyContentEnd 從后往前排列
  • ASStackLayoutJustifyContentSpaceBetween 間隔排列,兩端無間隔
  • ASStackLayoutJustifyContentSpaceAround 間隔排列贿讹,兩端有間隔
    4.alignItems: 交叉軸上的排列方式渐逃,有五個可選值:
  • ASStackLayoutAlignItemsStart 從前往后排列
  • ASStackLayoutAlignItemsEnd 從后往前排列
  • ASStackLayoutAlignItemsCenter 居中排列
  • ASStackLayoutAlignItemsStretch 拉伸排列
  • ASStackLayoutAlignItemsBaselineFirst 以第一個文字元素基線排列(主軸是橫向才可用)
  • ASStackLayoutAlignItemsBaselineLast 以最后一個文字元素基線排列(主軸是橫向才可用)
    5.children: 包含的視圖。數(shù)組內(nèi)元素順序同樣代表著布局時排列的順序

四民褂、優(yōu)缺點

  • 不支持大家常用的storyboard茄菊、xib、autoLayout赊堪,影響開發(fā)效率
  • 代碼沒有UIKit使用熟練
  • 網(wǎng)上資源少
  • 但是可以和UIKit混合開發(fā)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末面殖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子哭廉,更是在濱河造成了極大的恐慌脊僚,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件群叶,死亡現(xiàn)場離奇詭異吃挑,居然都是意外死亡钝荡,警方通過查閱死者的電腦和手機(jī)街立,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來埠通,“玉大人赎离,你說我怎么就攤上這事《巳瑁” “怎么了梁剔?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長舞蔽。 經(jīng)常有香客問我荣病,道長,這世上最難降的妖魔是什么渗柿? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任个盆,我火速辦了婚禮,結(jié)果婚禮上朵栖,老公的妹妹穿的比我還像新娘颊亮。我一直安慰自己,他們只是感情好陨溅,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布终惑。 她就那樣靜靜地躺著,像睡著了一般门扇。 火紅的嫁衣襯著肌膚如雪雹有。 梳的紋絲不亂的頭發(fā)上偿渡,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音霸奕,去河邊找鬼卸察。 笑死,一個胖子當(dāng)著我的面吹牛铅祸,可吹牛的內(nèi)容都是我干的坑质。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼临梗,長吁一口氣:“原來是場噩夢啊……” “哼涡扼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盟庞,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤吃沪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后什猖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體票彪,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年不狮,在試婚紗的時候發(fā)現(xiàn)自己被綠了降铸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡摇零,死狀恐怖推掸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情驻仅,我是刑警寧澤谅畅,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站噪服,受9級特大地震影響毡泻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜粘优,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一仇味、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧敬飒,春花似錦邪铲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春揽惹,著一層夾襖步出監(jiān)牢的瞬間被饿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工搪搏, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留狭握,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓疯溺,卻偏偏與公主長得像论颅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子囱嫩,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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

  • 1恃疯、通過CocoaPods安裝項目名稱項目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地數(shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,980評論 3 119
  • AsyncDisplayKit初體驗 AsyncDisplayKit不僅僅是一個工具,它更像一個系統(tǒng)UI框架墨闲,改變...
    MMD_閱讀 1,634評論 0 2
  • 內(nèi)容 關(guān)于圖層動畫相關(guān)框架的介紹 CoreAnimation結(jié)構(gòu)及圖層動畫 1. CoreGraphics今妄,Qua...
    smallSun15閱讀 1,223評論 1 13
  • 一大學(xué)生畢業(yè),分配到縣國有企業(yè)工作鸳碧。自認(rèn)為學(xué)富五車盾鳞,才高八斗。寫過散文詩歌小說甚至樂曲瞻离,但一個文字也沒發(fā)表過腾仅,...
    民族融合閱讀 386評論 0 0
  • 1. This flight has been delayed due to bad weather. 2. Th...
    PerfectPitch閱讀 398評論 0 0