mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-17 19:09:56 +00:00
Add a `usleep(1.0 * USEC_PER_SEC)` delay to ASBasicImageDownloader and slowly scroll through the Kittens sample project. Without this patch, you'll see that images only start downloading after their purple placeholders appear onscreen. With it, images can download and render before you scroll them onscreen, thanks to the working range.
326 lines
11 KiB
Objective-C
326 lines
11 KiB
Objective-C
/* Copyright (c) 2014-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
#import <pthread.h>
|
|
|
|
#import <AsyncDisplayKit/_ASDisplayLayer.h>
|
|
#import <AsyncDisplayKit/ASAssert.h>
|
|
#import <AsyncDisplayKit/ASDisplayNode.h>
|
|
#import <AsyncDisplayKit/ASThread.h>
|
|
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
|
|
@interface ASDisplayNode (Subclassing)
|
|
|
|
|
|
/** @name View Configuration */
|
|
|
|
|
|
/**
|
|
* @return The view class to use when creating a new display node instance. Defaults to _ASDisplayView.
|
|
*/
|
|
+ (Class)viewClass;
|
|
|
|
|
|
/** @name Properties */
|
|
|
|
|
|
/**
|
|
* @abstract The scale factor to apply to the rendering.
|
|
*
|
|
* @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.
|
|
*
|
|
* @see setNeedsDisplayAtScale:
|
|
*/
|
|
@property (nonatomic, assign, readonly) CGFloat contentsScaleForDisplay;
|
|
|
|
/**
|
|
* @abstract Whether the view or layer of this display node is currently in a window
|
|
*/
|
|
@property (nonatomic, readonly, assign, getter=isInHierarchy) BOOL inHierarchy;
|
|
|
|
|
|
/** @name View Lifecycle */
|
|
|
|
|
|
/**
|
|
* @abstract Called on the main thread immediately after self.view is created.
|
|
*
|
|
* @discussion This is the best time to add gesture recognizers to the view.
|
|
*/
|
|
- (void)didLoad ASDISPLAYNODE_REQUIRES_SUPER;
|
|
|
|
|
|
/** @name Layout */
|
|
|
|
|
|
/**
|
|
* @abstract Called on the main thread by the view's -layoutSubviews.
|
|
*
|
|
* @discussion Subclasses override this method to layout all subnodes or subviews.
|
|
*/
|
|
- (void)layout;
|
|
|
|
/**
|
|
* @abstract Called on the main thread by the view's -layoutSubviews, after -layout.
|
|
*
|
|
* @discussion Gives a chance for subclasses to perform actions after the subclass and superclass have finished laying
|
|
* out.
|
|
*/
|
|
- (void)layoutDidFinish;
|
|
|
|
|
|
/** @name Sizing */
|
|
|
|
|
|
/**
|
|
* @abstract Return the calculated size.
|
|
*
|
|
* @param 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 cached by ASDisplayNode for quick access during -layout, via -calculatedSize. 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 -calculatedSize instead.
|
|
*/
|
|
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize;
|
|
|
|
/**
|
|
* @abstract Invalidate previously measured and cached size.
|
|
*
|
|
* @discussion Subclasses should call this method to invalidate the previously measured and cached size for the display
|
|
* node, when the contents of the node change in such a way as to require measuring it again.
|
|
*/
|
|
- (void)invalidateCalculatedSize;
|
|
|
|
|
|
/** @name Drawing */
|
|
|
|
|
|
/**
|
|
* @summary Delegate method to draw layer contents into a CGBitmapContext. The current UIGraphics context will be set
|
|
* to an appropriate context.
|
|
*
|
|
* @param bounds Region to draw in.
|
|
* @param parameters An object describing all of the properties you need to draw. Return this from
|
|
* -drawParametersForAsyncLayer:
|
|
* @param 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.
|
|
* @param 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.
|
|
*
|
|
* @note Called on the display queue and/or main queue (MUST BE THREAD SAFE)
|
|
*/
|
|
+ (void)drawRect:(CGRect)bounds
|
|
withParameters:(id<NSObject>)parameters
|
|
isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock
|
|
isRasterizing:(BOOL)isRasterizing;
|
|
|
|
/**
|
|
* @summary Delegate override to provide new layer contents as a UIImage.
|
|
*
|
|
* @param parameters An object describing all of the properties you need to draw. Return this from
|
|
* -drawParametersForAsyncLayer:
|
|
* @param 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 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.
|
|
*
|
|
* @note Called on the display queue and/or main queue (MUST BE THREAD SAFE)
|
|
*/
|
|
+ (UIImage *)displayWithParameters:(id<NSObject>)parameters
|
|
isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock;
|
|
|
|
/**
|
|
* @abstract Delegate override for drawParameters
|
|
*
|
|
* @param layer The layer that will be drawn into.
|
|
*
|
|
* @note Called on the main thread only
|
|
*/
|
|
- (NSObject *)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer;
|
|
|
|
/**
|
|
* @abstract Indicates that the receiver is about to display.
|
|
*
|
|
* @discussion Subclasses may override this method to be notified when display (asynchronous or synchronous) is
|
|
* about to begin.
|
|
*/
|
|
- (void)displayWillStart ASDISPLAYNODE_REQUIRES_SUPER;
|
|
|
|
/**
|
|
* @abstract Indicates that the receiver has finished displaying.
|
|
*
|
|
* @discussion Subclasses may override this method to be notified when display (asynchronous or synchronous) has
|
|
* completed.
|
|
*/
|
|
- (void)displayDidFinish ASDISPLAYNODE_REQUIRES_SUPER;
|
|
|
|
|
|
/**
|
|
* @abstract Marks the receiver's bounds as needing to be redrawn, with a scale value.
|
|
*
|
|
* @param 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 -setNeedsDisplay, contentsScaleForDisplay
|
|
*/
|
|
- (void)setNeedsDisplayAtScale:(CGFloat)contentsScale;
|
|
|
|
/**
|
|
* @abstract Recursively calls setNeedsDisplayAtScale: on subnodes.
|
|
*
|
|
* @param 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.
|
|
*
|
|
* @see setNeedsDisplayAtScale:
|
|
* @see contentsScaleForDisplay
|
|
*/
|
|
- (void)recursivelySetNeedsDisplayAtScale:(CGFloat)contentsScale;
|
|
|
|
|
|
/** @name Touch handling */
|
|
|
|
|
|
/**
|
|
* @abstract Tells the node when touches began in its view.
|
|
*
|
|
* @param touches A set of UITouch instances.
|
|
* @param event A UIEvent associated with the touch.
|
|
*/
|
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
|
|
|
|
/**
|
|
* @abstract Tells the node when touches moved in its view.
|
|
*
|
|
* @param touches A set of UITouch instances.
|
|
* @param event A UIEvent associated with the touch.
|
|
*/
|
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
|
|
|
|
/**
|
|
* @abstract Tells the node when touches ended in its view.
|
|
*
|
|
* @param touches A set of UITouch instances.
|
|
* @param event A UIEvent associated with the touch.
|
|
*/
|
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
|
|
|
|
/**
|
|
* @abstract Tells the node when touches was cancelled in its view.
|
|
*
|
|
* @param touches A set of UITouch instances.
|
|
* @param event A UIEvent associated with the touch.
|
|
*/
|
|
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
|
|
|
|
|
|
/** @name Managing Gesture Recognizers */
|
|
|
|
|
|
/**
|
|
* @abstract Asks the node if a gesture recognizer should continue tracking touches.
|
|
*
|
|
* @param gestureRecognizer A gesture recognizer trying to recognize a gesture.
|
|
*/
|
|
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
|
|
|
|
|
|
/** @name Hit Testing */
|
|
|
|
|
|
/**
|
|
* @abstract Returns the view that contains the point.
|
|
*
|
|
* @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.)
|
|
*
|
|
* @param point A point specified in the node's local coordinate system (bounds).
|
|
* @param event The event that warranted a call to this method.
|
|
*
|
|
* @return 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.
|
|
*/
|
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
|
|
|
|
|
|
/** @name Observing node-related changes */
|
|
|
|
|
|
/**
|
|
* Called just before the view is added to a superview.
|
|
*/
|
|
- (void)willEnterHierarchy ASDISPLAYNODE_REQUIRES_SUPER;
|
|
|
|
/**
|
|
* Called after the view is removed from the window.
|
|
*/
|
|
- (void)didExitHierarchy ASDISPLAYNODE_REQUIRES_SUPER;
|
|
|
|
/**
|
|
* Provides an opportunity to clear backing store and other memory-intensive intermediates, such as text layout managers
|
|
* or downloaded content that can be written to a disk cache.
|
|
*
|
|
* @discussion Called by -recursivelyReclaimMemory. Base class implements self.contents = nil, clearing any backing
|
|
* store, for asynchronous regeneration when needed.
|
|
*/
|
|
- (void)reclaimMemory ASDISPLAYNODE_REQUIRES_SUPER;
|
|
|
|
|
|
/** @name Description */
|
|
|
|
|
|
/**
|
|
* @abstract Return a description of the node
|
|
*
|
|
* @discussion The function that gets called for each display node in -recursiveDescription
|
|
*/
|
|
- (NSString *)descriptionForRecursiveDescription;
|
|
|
|
@end
|
|
|
|
@interface ASDisplayNode (ASDisplayNodePrivate)
|
|
// This method has proven helpful in a few rare scenarios, similar to a category extension on UIView,
|
|
// but it's considered private API for now and its use should not be encouraged.
|
|
- (ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass;
|
|
@end
|
|
|
|
#define ASDisplayNodeAssertThreadAffinity(viewNode) ASDisplayNodeAssert(!viewNode || ASDisplayNodeThreadIsMain() || !(viewNode).nodeLoaded, @"Incorrect display node thread affinity")
|
|
#define ASDisplayNodeCAssertThreadAffinity(viewNode) ASDisplayNodeCAssert(!viewNode || ASDisplayNodeThreadIsMain() || !(viewNode).nodeLoaded, @"Incorrect display node thread affinity")
|