AsyncDisplayKit 初窺

了解 AsyncDisplayKit

AsyncDisplayKit的基本單位是節(jié)點 Node。一個Asdisplaynode 是 UIView 的抽象,反過來是CALayer抽象谓厘。與只能在主線程上使用的 UIView 視圖不同叮叹,節(jié)點是線程安全的:您可以在后臺線程上并行地實例化和配置它們的整個層次結(jié)構(gòu)。
為了保持它的用戶界面流暢和響應(yīng)派阱,你的應(yīng)用程序應(yīng)該以每秒60幀的速度呈現(xiàn)切诀。這意味著主線程有六十分之一秒把每幀揩环。這是16毫秒執(zhí)行所有的布局和繪圖代碼!而且由于系統(tǒng)開銷幅虑,您的代碼通常不到十毫秒才能運行它導(dǎo)致幀下降丰滑。
AsyncDisplayKit 讓你 Image 解碼、文本大小和渲染倒庵,布局吨枉,和其他昂貴的UI操作關(guān)閉主線程,讓主線程可以響應(yīng)用戶交互哄芜。

這段話翻譯于 AsyncDisplayKit GitHub 的介紹, 我們可以 通過 CocoaPods or Carthage 安裝使用; 另外 目前 AsyncDisplayKit 已經(jīng)改名為 Texture

關(guān)于 AsyncDisplayKit 的更多深層的理解, 本人參考了以下 文章

使用

為了更加深入理解 AsyncDisplayKit 這個框架, 我嘗試 進行 AsyncDisplayKit的簡單使用
基于

AsyncDisplayKit 2.2.1
Swift 4.0

ASTextNode

ASTextNode 相當于 UILabel , 不同的是 它不能設(shè)置 text 只能設(shè)置 attributedText

 // MARK:- Use ASTextNode
    func buildTextNode(textContent: String)  {
        let textLabel = ASTextNode()
        if !textContent.isEmpty {
            textLabel.attributedText = NSAttributedString(string: textContent, attributes:
                [NSAttributedStringKey.foregroundColor : UIColor.white,
                 NSAttributedStringKey.font : UIFont.systemFont(ofSize: 16),
                 NSAttributedStringKey.backgroundColor : UIColor.black]
            )
        }

        let margin:CGFloat = 15
        let width:CGFloat = XW_SCREEN_WIDTH - margin * 2
        
        textLabel.layoutThatFits(ASSizeRange.init(min: CGSize.init(width: width, height: 30), max: CGSize.init(width: width, height: 300)))
        textLabel.frame = CGRect.init(x: margin, y: 90, width: textLabel.calculatedSize.width, height: textLabel.calculatedSize.height)
        
        self.view.addSubnode(textLabel)

    }

我們 可以使用 layoutThatFits 來自行計算, 自適應(yīng) label的內(nèi)容 , ASSizeRange 來限定 最小 和最大的 size
然后, 設(shè)置frame 我們可以直接獲取到 calculatedSize , 是不是 還是蠻方便的呢 ?
最后 使用 .addSubnode 代替 .addSubView

ASImageNode

    // MARK:- Use ASImageNode
    func buildImageNode(imageURLString: String) {
        let imageView = ASNetworkImageNode()
        imageView.frame = CGRect.init(x: 80, y: 400, width: 200, height: 200)
        imageView.backgroundColor = UIColor.green
        imageView.contentMode = .scaleAspectFill
        if !imageURLString.isEmpty {
            imageView.url = URL.init(string: imageURLString)
        }
        self.view.addSubnode(imageView)
    }

如果 你使用本地 的image 可能你只需要 使用 ASImageNode
但是加載 網(wǎng)絡(luò)圖片 就需要 使用到 ASNetworkImageNode

ASNetworkImageNode 默認用的緩存機制和圖片下載器是 PinRemoteImage认臊,為了使用我們自己的緩存機制和圖片下載器,需要實現(xiàn) ASImageCacheProtocol 圖片緩存協(xié)議和 ASImageDownloaderProtocol 圖片下載器協(xié)議兩個協(xié)議

ASButtonNode

 // MARK:- Use ASButtonNode
    func buildButtonNode(buttonName: String) {
        let buttonNode = ASButtonNode()
        if !buttonName.isEmpty {
            buttonNode.setTitle(buttonName, with: UIFont.systemFont(ofSize: 14), with: UIColor.black, for: UIControlState.normal)
        }
        buttonNode.backgroundColor = UIColor.yellow
        buttonNode.frame = CGRect.init(x: 80, y: 640, width: 200, height: 30)
        buttonNode.addTarget(self, action: #selector(clickedButton(sender:)), forControlEvents: .touchUpInside)
        self.view.addSubnode(buttonNode)
    }

需要 注意 ASButtonNode 繼承于 ASControlNode 可以設(shè)置 add target, 有屬性
ASTextNode * titleNode; ASImageNode * imageNode; ASImageNode * backgroundImageNode;

ASControlNode

ASImageNode锄奢、ASButtonNode失晴、ASTextNode 同為 ASControlNode 子類,可以直接使用 .addTarget(self, action: "handleXXX", forControlEvents: .TouchUpInside) 為它們添加點擊響應(yīng)事件拘央,而避免使用addGesture等方法涂屁。

ASTableNode

我們可以使用 ASTableNode 來 著力解決 UITableView 在 ReloadData 耗時長以及滑動卡頓的性能問題

初始化 let tableView = ASTableNode.init(style: UITableViewStyle.plain)
代理 ASTableViewDataSource, ASTableViewDelegate

ASTableDataSource

 //MARK:- ASTableDataSource
    
    func numberOfSections(in tableNode: ASTableNode) -> Int {
        return 1
    }
    
    func tableNode(_ tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int {
        return mockData.count
    }
    
    func tableNode(_ tableNode: ASTableNode, nodeForRowAt indexPath: IndexPath) -> ASCellNode {
        let cellNode = CustomCellNode()
        return cellNode
     }
     
     .....

ASTableDataSource

 //MARK:-  ASTableDelegate
    func tableNode(_ tableNode: ASTableNode, didSelectRowAt indexPath: IndexPath) {
 
    }
 
    func tableNode(_ tableNode: ASTableNode, willDisplayRowWith node: ASCellNode) {
    
  }
  
  ..... 

需要注意 ASTableNode 的高度計算以及布局都在 ASCellNode 中實現(xiàn),與 ASTableNode 是完全解耦的灰伟。
ASTableNode 中所有的元素都不支持 AutoLayout拆又、AutoResizing儒旬,也不支持StoryBoard、IB帖族。
ASTableNode 完全可以將滑動性能提升至60FPS栈源。
ASTableNode 實質(zhì)上是一個 ScrollView ,其中添加有指定數(shù)的 ASDisplayNode竖般,在屏幕滾動時甚垦,離屏的ASDisplayNode內(nèi)容會被暫時釋放,在屏或接近在屏的ASDisplayNode會被提前加載涣雕。因此艰亮,ASTableView 不存在 Cell 復(fù)用的問題,也不存在任何 Cell 復(fù)用挣郭。

ASCellNode

通常我們 自定義 UITableViewCell 是繼承于 ASCellNode
執(zhí)行以下步驟

  • override init() 創(chuàng)建 對應(yīng) 的 node, 添加進去
  • 添加數(shù)據(jù) function
  • override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize 計算控件寬度和高度迄埃,并返回 Cell 的高度, 我們一般 需要計算的 東西 都是在這個方法里面進行 layoutThatFits
  • override func layout() 各個控件 進行布局 , 通常 調(diào)用 calculatedSize 進行 自適應(yīng)布局

ASDisplayNode

對于一些 不支持 的控件, 列如 UISlider, UISwitch, UIActivityIndicatorView, 并沒有對應(yīng)的 ASDisplayNode 子類實現(xiàn)。因此丈屹,我們需要創(chuàng)建一個 ASDisplayNode 调俘,使用block方法返回;

這里以一個 UIActivityIndicatorView 為例

    let activityIndicator = ASDisplayNode.init(viewBlock: { () -> UIView in
        let view = UIActivityIndicatorView(activityIndicatorStyle: .gray)
        view.backgroundColor = UIColor.clear
        view.hidesWhenStopped = true
        return view
    })

使用同樣的方法,可以添加任意類型 UIView 到 CellNode 中旺垒,這樣就不需要被 AsyncDisplayKit 束縛我們的應(yīng)用了彩库。

使用感想

首先, 本文只是對 AsyncDisplayKit 的一些基礎(chǔ) 控件 進行初窺使用; 通過 Node 的使用方式 和 UIView 有著 相似 的一些 代碼 特性; Node 會暴露 出 view 的一些基礎(chǔ)屬性 和 UIView 使用一樣, 這令我們的學(xué)習(xí)成本 有一定降低; 一些不會明顯暴露的屬性,也可以通過 node.view 來獲取到, 讓初次接觸 框架的人 比較容易上手。

其次, AsyncDisplayKit 是線程 絕對 安全的, 能保證 一些復(fù)雜的界面也穩(wěn)定 60fps 運行, 開發(fā)者不比去考慮 Image 解碼先蒋、文本大小和渲染等 帶來的線程堵塞, 有利于程序的性能優(yōu)化骇钦。 同事 使用 AsyncDisplayKit 來開發(fā), 代碼的條理 變得 清晰, 通過 ASCellNode 能夠完全和 ASTableNode 進行解耦來看, 各種優(yōu)點會讓程序變得更加容易維護。

于此同時, AsyncDisplayKit 帶來的負面影響也是不容忽視的;由于ASDK的基本理念是在需要創(chuàng)建UIView時替換成對應(yīng)的Node來獲取性能提升竞漾,因此對于現(xiàn)有代碼改動較大眯搭,侵入性較高,同時由于大量原本熟悉的操作變成了異步的业岁,對于一個團隊來說學(xué)習(xí)曲線也較為陡峭鳞仙。

AsyncDisplayKit 不支持 AutoLayout、AutoResizing笔时,也不支持StoryBoard棍好、IB。這 似乎 與 Apple 的理念相違背; Apple 是鼓勵使用 可視化進行編程的允耿。

綜合來分析, AsyncDisplayKit 是一個非常的不錯框架; 考慮到AsyncDisplayKit的種種好處借笙,非常推薦AsyncDisplayKit,當然還是僅限于用在比較復(fù)雜和動態(tài)的頁面中较锡。不需要也不可能將所有UIView都替換成其Node版本业稼。將注意力集中在可能造成主線程阻塞的地方,如tableView/collectionView蚂蕴、復(fù)雜布局的View低散、使用連續(xù)手勢的操作等等俯邓。

Link

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谦纱,隨后出現(xiàn)的幾起案子看成,更是在濱河造成了極大的恐慌,老刑警劉巖跨嘉,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件川慌,死亡現(xiàn)場離奇詭異,居然都是意外死亡祠乃,警方通過查閱死者的電腦和手機梦重,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來亮瓷,“玉大人琴拧,你說我怎么就攤上這事≈鲋В” “怎么了蚓胸?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長除师。 經(jīng)常有香客問我沛膳,道長,這世上最難降的妖魔是什么汛聚? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任锹安,我火速辦了婚禮,結(jié)果婚禮上倚舀,老公的妹妹穿的比我還像新娘叹哭。我一直安慰自己,他們只是感情好痕貌,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布风罩。 她就那樣靜靜地躺著,像睡著了一般舵稠。 火紅的嫁衣襯著肌膚如雪泊交。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天柱查,我揣著相機與錄音,去河邊找鬼云石。 笑死唉工,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的汹忠。 我是一名探鬼主播淋硝,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼雹熬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谣膳?” 一聲冷哼從身側(cè)響起竿报,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎继谚,沒想到半個月后烈菌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡花履,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年芽世,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诡壁。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡济瓢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出妹卿,到底是詐尸還是另有隱情旺矾,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布夺克,位于F島的核電站箕宙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏懊直。R本人自食惡果不足惜扒吁,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望室囊。 院中可真熱鬧雕崩,春花似錦、人聲如沸融撞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尝偎。三九已至饶火,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間致扯,已是汗流浹背肤寝。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抖僵,地道東北人鲤看。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像耍群,于是被迫代替她去往敵國和親义桂。 傳聞我的和親對象是個殘疾皇子找筝,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

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