集成
集成 AsyncDisplayKit 非常简单,使用 CocoaPods 添加 pod "AsyncDisplayKit"
然后 pod update 就可以了。什么?你还不愿意使用 CocoaPods?那你手动集成好了。
AsyncDisplayKit 只支持 iOS7.0 版本以上的系统,如果你使用的是 Swift,那么还需要将头文件引用 #import <AsyncDisplayKit/AsyncDisplayKit.h>
添加到 Swift-Bridging.h
中。
以下教程均使用 Swift 演示代码,Objective-C 使用方法也是类似的。
Hello, World!
一个 Demo 就应该从 ** Hello, World! ** 开始。
在 ViewController.swift 中添加以下代码
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textLabel = ASTextNode()
textLabel.attributedString = NSAttributedString(string: "Hello, World!",
attributes: [
NSForegroundColorAttributeName: UIColor.blackColor(),
NSFontAttributeName: UIFont.systemFontOfSize(17)
])
textLabel.frame = CGRect(x: 50, y: 50, width: 100, height: 20)
self.view.addSubnode(textLabel)
}
}
我们做了些什么?
- 创建了一个ASTextNode的实例,名为textLabel;
- 为textLabel添加了一串富文本文字,并设定一些富文本属性,这里要注意,AsyncDisplayKit只支持富文本文字;
- 粗略地为textLabel设定一个frame;
- 把textLabel添加到view中。
整个过程其实和 UIView 的初始化并且 addSubview 没有太大的区别。 现在,你可以把 Demo Run 起来看看效果了。
控件对应关系
在 AsyncDisplayKit 的世界里,常用的 UIKit 控件都有对应的 AS 控件,以下是一个对照表。
UIKit | AsyncDisplayKit |
---|---|
UIView | ASDisplayNode |
UILabel | ASTextNode |
UIImageView | ASImageNode |
UIButton | ASButtonNode |
UITableView | ASTableView |
UICollectionView | ASCollectionView |
UITableViewCell | ASCellNode |
UICollectionViewCell | ASCellNode |
ASDisplayNode 是所有控件的基类,它是整个 AsyncDisplayKit 界面库的核心,ASDisplayNode 不仅可以承载 AsyncDisplayKit 预定义的控件(例如 ASTextNode),也可以承载 UIKit 控件(例如 UISlider)。
使用Block方法返回 UIView 就可以承载 UIKit 控件
let slider = ASDisplayNode { () -> UIView! in
return UISlider()
}
Measure ASTextNode
还记得刚刚我们只是粗略地设置了一下 textLabel.frame 吗?我们当然是希望textLabel中的文字有多大,它的frame就有多大。
在AsyncDisplayKit的世界中,我们不需要使用 NSAttributedString.boundingRectWithSize去计算ASTextNode的宽高。
我们使用以下方法去计算文本的宽高。
textLabel.measure(CGSize(width: view.bounds.width, height: CGFloat.max))
textLabel.frame = CGRect(x: 0, y: 50, width: textLabel.calculatedSize.width, height: textLabel.calculatedSize.height)
给定measure方法一个CGSize的参数,该参数定义了textLabel的最大宽度和最大高度,使用textLabel.calculatedSize获取计算好的宽高。
你会在后续的教程中知道,measure的强大之处。
ASImageNode
ASImageNode 是 UIImageView 的极佳替代品,ASImageNode 会在后台线程渲染好 UIImage ,然后再在主线程中呈现图像。 因此,ASImageNode可以极大地提升FPS数值。
如果是本地图像,你可以直接将一个 UIImage 实例赋值到 ASImageNode.image 中。
如果是网络图像,你应该使用 ASNetworkImageNode, 同时你需要为 ASNetworkImageNode 指定一个 ImageManager 用于管理网络请求、图像缓存等操作,一般搭配 SDWebImage 使用,你可以将以下的代码直接拷贝使用。
class ImageManager: NSObject, ASImageDownloaderProtocol, ASImageCacheProtocol {
static let sharedManager = ImageManager()
func fetchCachedImageWithURL(URL: NSURL!, callbackQueue: dispatch_queue_t!, completion: ((CGImage!) -> Void)!) {
SDWebImageManager.sharedManager().cachedImageExistsForURL(URL) { (existed) -> Void in
if existed {
SDWebImageManager.sharedManager().downloadImageWithURL(URL, options: [], progress: nil, completed: { (cachedImage, _, _, _, _) -> Void in
dispatch_async(callbackQueue, { () -> Void in
if let image = cachedImage {
if let cImage = image.CGImage {
dispatch_async(callbackQueue, { () -> Void in
completion(cImage)
})
return
}
}
completion(nil)
})
})
}
else {
dispatch_async(callbackQueue, { () -> Void in
completion(nil)
})
}
}
}
func downloadImageWithURL(URL: NSURL!, callbackQueue: dispatch_queue_t!, downloadProgressBlock: ((CGFloat) -> Void)!, completion: ((CGImage!, NSError!) -> Void)!) -> AnyObject! {
print(URL)
let operation = SDWebImageDownloader.sharedDownloader().downloadImageWithURL(URL, options: [], progress: nil) { (image, data, error, _) -> Void in
if let image = image {
if let cImage = image.CGImage {
dispatch_async(callbackQueue, { () -> Void in
completion(cImage, error)
})
return
}
}
completion(nil, error)
}
return operation
}
func cancelImageDownloadForIdentifier(downloadIdentifier: AnyObject!) {
if let downloadIdentifier = downloadIdentifier as? SDWebImageOperation {
downloadIdentifier.cancel()
}
}
}
添加一个 imageView 到 View 中。
let imageView = ASNetworkImageNode(cache: ImageManager.sharedManager,
downloader: ImageManager.sharedManager)
imageView.frame = CGRect(x: 0, y: 100, width: view.bounds.size.width, height: 300)
imageView.contentMode = .ScaleAspectFill
imageView.clipsToBounds = true
imageView.URL = NSURL(string: "http://ww3.sinaimg.cn/large/7191b2ebgw1eyb1uontv4j21w02iou0r.jpg")!
self.view.addSubnode(imageView)
ASControlNode
ASImageNode、ASButtonNode、ASTextNode 同为 ASControlNode 子类,可以直接使用 .addTarget(self, action: "handleXXX", forControlEvents: .TouchUpInside)
为它们添加点击响应事件,而避免使用addGesture等方法。
结语
关于其它控件的使用方法,需要你自己去学习使用,此遍教程的Demo代码,你可以到这里下载 https://github.com/PonyCui/AsyncDisplayKit-Issue-2