ASDisplayNode

Basic Node

ASDisplayNodeUIViewCALayer 를 추상화 한 메인 뷰입니다. UIViewCALayer 를 만들고 소유하는 것과 같은 방식으로 UIView 를 생성하고 소유합니다.
let node = ASDisplayNode()
node.backgroundColor = .orange
node.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
print("Underlying view: \(node.view)")
node 는 UIView 가 가지고 있는 프로퍼티를 동일하게 가지고 있어, UIKit 에 익숙한 사람들이라면 친숙하게 받아들일 수 있습니다.
let node = ASDisplayNode()
node.clipsToBounds = true // not .masksToBounds
node.borderColor = UIColor.blue.cgColor // layer name when there is no UIView equivalent
print("Backing layer: \(node.layer)")
위의 코드를 보면 알 수 있듯이 node 에서도 일반적인 UIView 를 다룰 때와 마찬가지로 CALayer 에 접근할 수 있습니다.
Node Container 와 함께 사용하면 node 의 프로퍼티는 background thread 에서 설정되고, node 에 캐시된 프로퍼티로 뷰와 레이어는 lazy 하게 구성됩니다.

View Wrapping

Node 를 생성할 때 UIView 도 사용할 수 있습니다. ( 생성자의 viewBlock 에 반환 ) 이 경우 Node 의 Display 단계가 동시에 발생합니다. 왜냐하면 Node 가 UIView 가 아닌 _ASDisplayView 를 Wrapping 하고 있을 때만 비동기 적으로 Display 되기 때문입니다.
let node = ASDisplayNode(viewBlock: { () -> UIView in
let view = UIView()
return view
})
위의 예시처럼 UIView 서브 클래스를 ASDisplayNode 서브 클래로 쉽게 변환할 수 있습니다.

SafeArea Insets

Texture 2.7부터 safeAreaInsets을 지원합니다. #available(iOS 11.0, *) 로 safeAreaInsets사용에 대해서 분기하실 필요가 없습니다.
사용시 유의해야할 점은
  • ViewController와 가장 밀접한 Node에서 접근하셔야됩니다. (그 이외 자식노드에선 항상 UIEdgeInsets이 zero 값입니다.)
  • automaticallyRelayoutOnSafeAreaChanges flag를 활성화 시켜야합니다. 활성화시키면 safeArea 값이 변화할 때마다 layout을 다시 그려냅니다.
let node = ASDisplayNode()
node.automaticallyRelayoutOnSafeAreaChanges = true
let safeAreaInsets: UIEdgeInsets = self.node.safeAreaInsets

drawRect:

final class TestView : UIView {
override func draw(_ rect: CGRect) {
// somthing
}
}
기존 UIView에서 제공되는 draw:와 같이 ASDisplayNode에서 Core Graphics 및 UIKit과 같은 기술을 사용하여 뷰의 내용을 그리기 위해서는 아래의 static draw method를 재정의(override)하고 드로잉 코드를 추가할 수 있습니다.
final class TestNode: ASDisplayNode {
static override func draw(
_ bounds: CGRect,
withParameters parameters: Any?,
isCancelled isCancelledBlock: () -> Bool,
isRasterizing: Bool
) {
// Example
let context = UIGraphicsGetCurrentContext()
context?.saveGState()
let path = UIBezierPath(ovalIn: CGRect(x:0, y:0, width:100, height:100))
UIColor.carrot500.setFill()
path.fill()
context?.restoreGState()
}
}