AsyncDisplayKit入門指南

jopen 10年前發布 | 28K 次閱讀 iOS開發 移動開發 AsyncDisplayKit

AsyncDisplayKit入門指南

非死book前兩天發布了其iOS UI框架AsyncDisplayKit(ASDK)的1.0正式版,這個框架被用于非死book自家的應用Paper,能夠提高UI的流暢性并縮短響應時間。

下載和使用

你可以使用CocoaPods來安裝AsyncDisplayKit,在Podfile中添加:

pod 'AsyncDisplayKit'

OC中導入框架header,如果用Swift則可以創建Objective-C bridging header:

#import <AsyncDisplayKit/AsyncDisplayKit.h>

概述

AsyncDisplayKit(ASDK)的基本單元是node,ASDisplayNode是UIView之上的抽象層,因此同時也是 CALayer的抽象層。和只能被用在主線程的視圖不同,nodes是線程安全的:你能并行的實例化并設置整個node層級,并且在后臺線程里運行。

為了保證它的用戶界面的流暢和響應,你的app渲染幀率應該和iOS基準保持同步,即60幀每秒。這意味著主線程對每一幀有60分之一的時間來推送,這大約是16毫秒,需要在如此短時間內來執行所有的布局和繪制的代碼。而由于系統的性能開銷,在導致丟幀之前,你的代碼通常只有不到10毫秒的時間來執行。

AsyncDisplayKit讓你將圖像解碼、調整文字大小并渲染,以及其他高耗時的UI操作移出主線程。當然它還有其他的一些功能,你可以在官方文檔中探索。

作為視圖直接替代的Node

如果你之前處理過視圖,那么你已經知道如何使用node了。Node的API也類似于UIView,不過更方便。比如,你能直接讀取公共的CALayer屬性。添加一個node到現有的視圖或層級,使用node.view或node.layer。

AsyncDisplayKit包括一些強力的組件:

  • ASDisplayNode. UIView的副本 — 一個子類,用來自定義node。
  • ASControlNode. 類似于UIControl — 用來制作按鈕的子類。
  • ASImageNode. 類似于UIImageView — 異步的解碼圖像資源。
  • ASTextNode. 類似于UITextView — 基于TextKit構建,支持富文本的全部特性。
  • ASTableView. UITableView子類,用于支持node。

你可以將這些用作UIKit副本的直接替代。即便ASDK在完整的基于node的層級下工作十分高效,使用node替代獨立視圖能夠更加的提高性能。

讓我們來看一個例子。

我們一開始在主線程中異步的使用node——和你平常使用視圖的方式一樣。我們的代碼和自定義視圖控制器-loadView的實現差不多:

_imageView = [[UIImageView alloc] init];
_imageView.image = [UIImage imageNamed:@"hello"];
_imageView.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f);
[self.view addSubview:_imageView];

我們能使用如下基于node的代碼來替代它:

_imageNode = [[ASImageNode alloc] init];
_imageNode.backgroundColor = [UIColor lightGrayColor];
_imageNode.image = [UIImage imageNamed:@"hello"];
_imageNode.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f);
[self.view addSubview:_imageNode.view];

這并沒有利用ASDK的異步調整大小和布局的功能,但已經有所改進了。第一段代碼在主線程解碼hello.png,第二段則在后臺線程解碼圖像,并可能利用不同的CPU核心。

(注意我們在node中設置了占位符的背景顏色,它會占據屏幕直到真正的內容出現。這種做法對于圖像很好,但不太適用于文字——人們期望文字能直接展示,圖片則允許有加載延遲。我們后面會討論如何改進的技術。)

node按鈕

ASImageNode和ASTextNode都繼承了ASControlNode,所以你能將它們當做按鈕使用。假設我們在開發音樂播放器,并且希望添加(非擬物化的,iOS 7風格)隨機播放按鈕。

1-shuffle-crop

我們的視圖控制器代碼將和下面的差不多:

- (void)viewDidLoad
{
  [super viewDidLoad];

  // attribute a string
  NSDictionary *attrs = @{
                          NSFontAttributeName: [UIFont systemFontOfSize:12.0f],
                          NSForegroundColorAttributeName: [UIColor redColor],
                          };
  NSAttributedString *string = [[NSAttributedString alloc] initWithString:@"shuffle"
                                                               attributes:attrs];

  // create the node
  _shuffleNode = [[ASTextNode alloc] init];
  _shuffleNode.attributedString = string;

  // configure the button
  _shuffleNode.userInteractionEnabled = YES; // opt into touch handling
  [_shuffleNode addTarget:self
                   action:@selector(buttonTapped:)
         forControlEvents:ASControlNodeEventTouchUpInside];

  // size all the things
  CGRect b = self.view.bounds; // convenience
  CGSize size = [_shuffleNode measure:CGSizeMake(b.size.width, FLT_MAX)];
  CGPoint origin = CGPointMake(roundf( (b.size.width - size.width) / 2.0f ),
                               roundf( (b.size.height - size.height) / 2.0f ));
  _shuffleNode.frame = (CGRect){ origin, size };

  // add to our view
  [self.view addSubview:_shuffleNode.view];
}

- (void)buttonTapped:(id)sender
{
  NSLog(@"tapped!");
}

這段代碼能正常工作。不幸的是,這個按鈕只有14?個像素點高,離標準的44×44最小點擊尺寸相距甚遠,因此很難點擊到。我們能夠通過為 text node創建子類,并且覆蓋-hitTest:withEvent:來解決這個問題。我們甚至能強制text view在布局中的最低高度,但如果有更優雅的解決辦法不是更好嗎?

  // size all the things
  /* ... */

  // make the tap target taller
  CGFloat extendY = roundf( (44.0f - size.height) / 2.0f );
  _shuffleNode.hitTestSlop = UIEdgeInsetsMake(-extendY, 0.0f, -extendY, 0.0f);

就是這樣!Hit-test slops在所有node中都能正常工作,并且是一個展示這個新的抽象層能干什么的極好的示例。

后面還會講如何自定義node、異步的工作方式、最大限度的利用AsyncDisplayKit等,感興趣的可以查看官方文檔

來自:http://idlelife.org/archives/733

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!