ASDisplayNode(Subclassing) Category Reference

Declared in ASDisplayNode+Subclasses.h

Overview

The subclass header ASDisplayNode+Subclasses defines the following methods that either must or can be overriden by subclasses of ASDisplayNode.

These methods should never be called directly by other classes.

Drawing

Implement one of +displayWithParameters:isCancelled: or +drawRect:withParameters:isCancelled: to provide drawing for your node.

Use -drawParametersForAsyncLayer: to copy any properties that are involved in drawing into an immutable object for use on the display queue. The display and drawRect implementations MUST be thread-safe, as they can be called on the displayQueue (asynchronously) or the main thread (synchronously/displayImmediately).

Class methods that require passing in copies of the values are used to minimize the need for locking around instance variable access, and the possibility of the asynchronous display pass grabbing an inconsistent state across multiple variables.

Properties

  calculatedLayout

Return the calculated layout.

@property (nullable, nonatomic, readonly, assign) ASLayout *calculatedLayout

Return Value

Layout that wraps calculated size returned by -calculateSizeThatFits: (in manual layout mode), or layout already calculated from layout spec returned by -layoutSpecThatFits: (in automatic layout mode).

Discussion

For node subclasses that implement manual layout (e.g., they have a custom -layout method), calculatedLayout may be accessed on subnodes to retrieved cached information about their size. This allows -layout to be very fast, saving time on the main thread. Note: .calculatedLayout will only be set for nodes that have had -measure: called on them. For manual layout, make sure you call -measure: in your implementation of -calculateSizeThatFits:.

For node subclasses that use automatic layout (e.g., they implement -layoutSpecThatFits:), it is typically not necessary to use .calculatedLayout at any point. For these nodes, the ASLayoutSpec implementation will automatically call -measureWithSizeRange: on all of the subnodes, and the ASDisplayNode base class implementation of -layout will automatically make use of .calculatedLayout on the subnodes.

Warning: Subclasses must not override this; it returns the last cached layout and is never expensive.

Declared In

ASDisplayNode+Subclasses.h

View Lifecycle

– didLoad

Called on the main thread immediately after self.view is created.

- (void)didLoad

Discussion

This is the best time to add gesture recognizers to the view.

Declared In

ASDisplayNode+Subclasses.h

Layout

– layout

Called on the main thread by the view’s -layoutSubviews.

- (void)layout

Discussion

Subclasses override this method to layout all subnodes or subviews.

Declared In

ASDisplayNode+Subclasses.h

– layoutDidFinish

Called on the main thread by the view’s -layoutSubviews, after -layout.

- (void)layoutDidFinish

Discussion

Gives a chance for subclasses to perform actions after the subclass and superclass have finished laying out.

Declared In

ASDisplayNode+Subclasses.h

– calculatedLayoutDidChange

Called on a background thread if !isNodeLoaded - called on the main thread if isNodeLoaded.

- (void)calculatedLayoutDidChange

Discussion

When the .calculatedLayout property is set to a new ASLayout (directly from -calculateLayoutThatFits: or calculated via use of -layoutSpecThatFits:), subclasses may inspect it here.

Declared In

ASDisplayNode+Subclasses.h

Layout calculation

– calculateLayoutThatFits:

Calculate a layout based on given size range.

- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize

Parameters

constrainedSize

The minimum and maximum sizes the receiver should fit in.

Return Value

An ASLayout instance defining the layout of the receiver (and its children, if the box layout model is used).

Discussion

This method is called on a non-main thread. The default implementation calls either -layoutSpecThatFits: or -calculateSizeThatFits:, whichever method is overriden. Subclasses rarely need to override this method, override -layoutSpecThatFits: or -calculateSizeThatFits: instead.

Note: This method should not be called directly outside of ASDisplayNode; use -measure: or -calculatedLayout instead.

Declared In

ASDisplayNode+Subclasses.h

– calculateLayoutThatFits:restrictedToSize:relativeToParentSize:

ASDisplayNode’s implementation of -layoutThatFits:parentSize: calls this method to resolve the node’s size against parentSize, intersect it with constrainedSize, and call -calculateLayoutThatFits: with the result.

- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize restrictedToSize:(ASLayoutElementSize)size relativeToParentSize:(CGSize)parentSize

Discussion

In certain advanced cases, you may want to customize this logic. Overriding this method allows you to receive all three parameters and do the computation yourself.

Warning: Overriding this method should be done VERY rarely.

Declared In

ASDisplayNode+Subclasses.h

– calculateSizeThatFits:

Return the calculated size.

- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize

Parameters

constrainedSize

The maximum size the receiver should fit in.

Discussion

Subclasses that override should expect this method to be called on a non-main thread. The returned size is wrapped in an ASLayout and cached for quick access during -layout. Other expensive work that needs to be done before display can be performed here, and using ivars to cache any valuable intermediate results is encouraged.

Note: Subclasses that override are committed to manual layout. Therefore, -layout: must be overriden to layout all subnodes or subviews.

Note: This method should not be called directly outside of ASDisplayNode; use -layoutThatFits: or layoutThatFits:parentSize: instead.

Declared In

ASDisplayNode+Subclasses.h

– layoutSpecThatFits:

Return a layout spec that describes the layout of the receiver and its children.

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize

Parameters

constrainedSize

The minimum and maximum sizes the receiver should fit in.

Discussion

Subclasses that override should expect this method to be called on a non-main thread. The returned layout spec is used to calculate an ASLayout and cached by ASDisplayNode for quick access during -layout. Other expensive work that needs to be done before display can be performed here, and using ivars to cache any valuable intermediate results is encouraged.

Note: This method should not be called directly outside of ASDisplayNode; use -measure: or -calculatedLayout instead.

Warning: Subclasses that implement -layoutSpecThatFits: must not use .layoutSpecBlock. Doing so will trigger an exception. A future version of the framework may support using both, calling them serially, with the .layoutSpecBlock superseding any values set by the method override.

Declared In

ASDisplayNode+Subclasses.h

– invalidateCalculatedLayout

Invalidate previously measured and cached layout.

- (void)invalidateCalculatedLayout

Discussion

Subclasses should call this method to invalidate the previously measured and cached layout for the display node, when the contents of the node change in such a way as to require measuring it again.

Declared In

ASDisplayNode+Subclasses.h

Drawing

+ drawRect:withParameters:isCancelled:isRasterizing:

@summary Delegate method to draw layer contents into a CGBitmapContext. The current UIGraphics context will be set to an appropriate context.

+ (void)drawRect:(CGRect)bounds withParameters:(nullable id<NSObject>)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock isRasterizing:(BOOL)isRasterizing

Parameters

bounds

Region to draw in.

parameters

An object describing all of the properties you need to draw. Return this from -drawParametersForAsyncLayer:

isCancelledBlock

Execute this block to check whether the current drawing operation has been cancelled to avoid unnecessary work. A return value of YES means cancel drawing and return.

isRasterizing

YES if the layer is being rasterized into another layer, in which case drawRect: probably wants to avoid doing things like filling its bounds with a zero-alpha color to clear the backing store.

Discussion

Note: Called on the display queue and/or main queue (MUST BE THREAD SAFE)

Declared In

ASDisplayNode+Subclasses.h

+ displayWithParameters:isCancelled:

@summary Delegate override to provide new layer contents as a UIImage.

+ (nullable UIImage *)displayWithParameters:(nullable id<NSObject>)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock

Parameters

parameters

An object describing all of the properties you need to draw. Return this from -drawParametersForAsyncLayer:

isCancelledBlock

Execute this block to check whether the current drawing operation has been cancelled to avoid unnecessary work. A return value of YES means cancel drawing and return.

Return Value

A UIImage with contents that are ready to display on the main thread. Make sure that the image is already decoded before returning it here.

Discussion

Note: Called on the display queue and/or main queue (MUST BE THREAD SAFE)

Declared In

ASDisplayNode+Subclasses.h

– drawParametersForAsyncLayer:

Delegate override for drawParameters

- (nullable id<NSObject>)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer

Parameters

layer

The layer that will be drawn into.

Discussion

Note: Called on the main thread only

Declared In

ASDisplayNode+Subclasses.h

– displayWillStart

Indicates that the receiver is about to display.

- (void)displayWillStart

Discussion

Subclasses may override this method to be notified when display (asynchronous or synchronous) is about to begin.

Note: Called on the main thread only

Declared In

ASDisplayNode+Subclasses.h

– displayDidFinish

Indicates that the receiver has finished displaying.

- (void)displayDidFinish

Discussion

Subclasses may override this method to be notified when display (asynchronous or synchronous) has completed.

Note: Called on the main thread only

Declared In

ASDisplayNode+Subclasses.h

Observing node-related changes

– interfaceStateDidChange:fromState:

Called whenever any bit in the ASInterfaceState bitfield is changed.

- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState

Discussion

Subclasses may use this to monitor when they become visible, should free cached data, and much more.

See Also

Declared In

ASDisplayNode+Subclasses.h

– didEnterVisibleState

Called whenever the node becomes visible.

- (void)didEnterVisibleState

Discussion

Subclasses may use this to monitor when they become visible.

Note: This method is guaranteed to be called on main.

Declared In

ASDisplayNode+Subclasses.h

– didExitVisibleState

Called whenever the node is no longer visible.

- (void)didExitVisibleState

Discussion

Subclasses may use this to monitor when they are no longer visible.

Note: This method is guaranteed to be called on main.

Declared In

ASDisplayNode+Subclasses.h

– didEnterDisplayState

Called whenever the the node has entered the display state.

- (void)didEnterDisplayState

Discussion

Subclasses may use this to monitor when a node should be rendering its content.

Note: This method is guaranteed to be called on main.

Declared In

ASDisplayNode+Subclasses.h

– didExitDisplayState

Called whenever the the node has exited the display state.

- (void)didExitDisplayState

Discussion

Subclasses may use this to monitor when a node should no longer be rendering its content.

Note: This method is guaranteed to be called on main.

Declared In

ASDisplayNode+Subclasses.h

– didEnterPreloadState

Called whenever the the node has entered the preload state.

- (void)didEnterPreloadState

Discussion

Subclasses may use this to monitor data for a node should be preloaded, either from a local or remote source.

Note: This method is guaranteed to be called on main.

Declared In

ASDisplayNode+Subclasses.h

– didExitPreloadState

Called whenever the the node has exited the preload state.

- (void)didExitPreloadState

Discussion

Subclasses may use this to monitor whether preloading data for a node should be canceled.

Note: This method is guaranteed to be called on main.

Declared In

ASDisplayNode+Subclasses.h

– willEnterHierarchy

Called just before the view is added to a window.

- (void)willEnterHierarchy

Declared In

ASDisplayNode+Subclasses.h

– didExitHierarchy

Called after the view is removed from the window.

- (void)didExitHierarchy

Declared In

ASDisplayNode+Subclasses.h

  inHierarchy

Whether the view or layer of this display node is currently in a window

@property (nonatomic, readonly, assign, getter=isInHierarchy) BOOL inHierarchy

Declared In

ASDisplayNode+Subclasses.h

– fetchData

Indicates that the node should fetch any external data, such as images.

- (void)fetchData

Discussion

Subclasses may override this method to be notified when they should begin to fetch data. Fetching should be done asynchronously. The node is also responsible for managing the memory of any data. The data may be remote and accessed via the network, but could also be a local database query.

Declared In

ASDisplayNode+Subclasses.h

– clearFetchedData

Provides an opportunity to clear any fetched data (e.g. remote / network or database-queried) on the current node.

- (void)clearFetchedData

Discussion

This will not clear data recursively for all subnodes. Either call -recursivelyClearFetchedData or selectively clear fetched data.

Declared In

ASDisplayNode+Subclasses.h

– clearContents

Provides an opportunity to clear backing store and other memory-intensive intermediates, such as text layout managers on the current node.

- (void)clearContents

Discussion

Called by -recursivelyClearContents. Base class implements self.contents = nil, clearing any backing store, for asynchronous regeneration when needed.

Declared In

ASDisplayNode+Subclasses.h

– subnodeDisplayWillStart:

Indicates that the receiver is about to display its subnodes. This method is not called if there are no subnodes present.

- (void)subnodeDisplayWillStart:(ASDisplayNode *)subnode

Parameters

subnode

The subnode of which display is about to begin.

Discussion

Subclasses may override this method to be notified when subnode display (asynchronous or synchronous) is about to begin.

Declared In

ASDisplayNode+Subclasses.h

– subnodeDisplayDidFinish:

Indicates that the receiver is finished displaying its subnodes. This method is not called if there are no subnodes present.

- (void)subnodeDisplayDidFinish:(ASDisplayNode *)subnode

Parameters

subnode

The subnode of which display is about to completed.

Discussion

Subclasses may override this method to be notified when subnode display (asynchronous or synchronous) has completed.

Declared In

ASDisplayNode+Subclasses.h

– setNeedsDisplayAtScale:

Marks the receiver’s bounds as needing to be redrawn, with a scale value.

- (void)setNeedsDisplayAtScale:(CGFloat)contentsScale

Parameters

contentsScale

The scale at which the receiver should be drawn.

Discussion

Subclasses should override this if they don’t want their contentsScale changed.

Note: This changes an internal property. -setNeedsDisplay is also available to trigger display without changing contentsScaleForDisplay.

See Also

Declared In

ASDisplayNode+Subclasses.h

– recursivelySetNeedsDisplayAtScale:

Recursively calls setNeedsDisplayAtScale: on subnodes.

- (void)recursivelySetNeedsDisplayAtScale:(CGFloat)contentsScale

Parameters

contentsScale

The scale at which the receiver’s subnode hierarchy should be drawn.

Discussion

Subclasses may override this if they require modifying the scale set on their child nodes.

Note: Only the node tree is walked, not the view or layer trees.

Declared In

ASDisplayNode+Subclasses.h

  contentsScaleForDisplay

The scale factor to apply to the rendering.

@property (nonatomic, assign, readonly) CGFloat contentsScaleForDisplay

Discussion

Use setNeedsDisplayAtScale: to set a value and then after display, the display node will set the layer’s contentsScale. This is to prevent jumps when re-rasterizing at a different contentsScale. Read this property if you need to know the future contentsScale of your layer, eg in drawParameters.

Declared In

ASDisplayNode+Subclasses.h

Touch handling

– touchesBegan:withEvent:

Tells the node when touches began in its view.

- (void)touchesBegan:(NSSet<UITouch*> *)touches withEvent:(nullable UIEvent *)event

Parameters

touches

A set of UITouch instances.

event

A UIEvent associated with the touch.

Declared In

ASDisplayNode+Subclasses.h

– touchesMoved:withEvent:

Tells the node when touches moved in its view.

- (void)touchesMoved:(NSSet<UITouch*> *)touches withEvent:(nullable UIEvent *)event

Parameters

touches

A set of UITouch instances.

event

A UIEvent associated with the touch.

Declared In

ASDisplayNode+Subclasses.h

– touchesEnded:withEvent:

Tells the node when touches ended in its view.

- (void)touchesEnded:(NSSet<UITouch*> *)touches withEvent:(nullable UIEvent *)event

Parameters

touches

A set of UITouch instances.

event

A UIEvent associated with the touch.

Declared In

ASDisplayNode+Subclasses.h

– touchesCancelled:withEvent:

Tells the node when touches was cancelled in its view.

- (void)touchesCancelled:(nullable NSSet<UITouch*> *)touches withEvent:(nullable UIEvent *)event

Parameters

touches

A set of UITouch instances.

event

A UIEvent associated with the touch.

Declared In

ASDisplayNode+Subclasses.h

Managing Gesture Recognizers

– gestureRecognizerShouldBegin:

Asks the node if a gesture recognizer should continue tracking touches.

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

Parameters

gestureRecognizer

A gesture recognizer trying to recognize a gesture.

Declared In

ASDisplayNode+Subclasses.h

Hit Testing

– hitTest:withEvent:

Returns the view that contains the point.

- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event

Parameters

point

A point specified in the node’s local coordinate system (bounds).

event

The event that warranted a call to this method.

Return Value

Returns a UIView, not ASDisplayNode, for two reasons: 1) allows sending events to plain UIViews that don’t have attached nodes, 2) hitTest: is never called before the views are created.

Discussion

Override to make this node respond differently to touches: (e.g. hide touches from subviews, send all touches to certain subviews (hit area maximizing), etc.)

Declared In

ASDisplayNode+Subclasses.h

Placeholders

– placeholderImage

Optionally provide an image to serve as the placeholder for the backing store while the contents are being displayed.

- (nullable UIImage *)placeholderImage

Discussion

Note: Called on the display queue and/or main queue (MUST BE THREAD SAFE)

Declared In

ASDisplayNode+Subclasses.h

Description

– descriptionForRecursiveDescription

Return a description of the node

- (NSString *)descriptionForRecursiveDescription

Discussion

The function that gets called for each display node in -recursiveDescription

Declared In

ASDisplayNode+Subclasses.h

– asyncTraitCollectionDidChange

Called when the node’s ASTraitCollection changes

- (void)asyncTraitCollectionDidChange

Discussion

Subclasses can override this method to react to a trait collection change.

Declared In

ASDisplayNode+Subclasses.h