mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-14 02:10:15 +00:00
Merge branch 'master' into update-objc
Conflicts: AsyncDisplayKit/ASDisplayNode+Subclasses.h
This commit is contained in:
commit
b16a9e294e
@ -21,8 +21,9 @@ typedef NSUInteger ASCellNodeAnimation;
|
||||
* The notification is done on main thread.
|
||||
*
|
||||
* @param node A node informing the delegate about the relayout.
|
||||
* @param sizeChanged `YES` if the node's `calculatedSize` changed during the relayout, `NO` otherwise.
|
||||
*/
|
||||
- (void)nodeDidRelayout:(ASCellNode *)node;
|
||||
- (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged;
|
||||
@end
|
||||
|
||||
/**
|
||||
|
||||
@ -53,11 +53,13 @@
|
||||
- (void)setNeedsLayout
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
CGSize oldSize = self.calculatedSize;
|
||||
[super setNeedsLayout];
|
||||
|
||||
if (_layoutDelegate != nil) {
|
||||
BOOL sizeChanged = !CGSizeEqualToSize(oldSize, self.calculatedSize);
|
||||
ASPerformBlockOnMainThread(^{
|
||||
[_layoutDelegate nodeDidRelayout:self];
|
||||
[_layoutDelegate nodeDidRelayout:self sizeChanged:sizeChanged];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,6 +156,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
BOOL _asyncDelegateImplementsInsetSection;
|
||||
BOOL _collectionViewLayoutImplementsInsetSection;
|
||||
BOOL _asyncDataSourceImplementsConstrainedSizeForNode;
|
||||
BOOL _queuedNodeSizeUpdate;
|
||||
|
||||
ASBatchContext *_batchContext;
|
||||
|
||||
@ -911,10 +912,26 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
|
||||
#pragma mark - ASCellNodeDelegate
|
||||
|
||||
- (void)nodeDidRelayout:(ASCellNode *)node
|
||||
- (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
// Cause UICollectionView to requery for the new height of this node
|
||||
|
||||
if (!sizeChanged || _queuedNodeSizeUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
_queuedNodeSizeUpdate = YES;
|
||||
[self performSelector:@selector(requeryNodeSizes)
|
||||
withObject:nil
|
||||
afterDelay:0
|
||||
inModes:@[ NSRunLoopCommonModes ]];
|
||||
}
|
||||
|
||||
// Cause UICollectionView to requery for the new size of all nodes
|
||||
- (void)requeryNodeSizes
|
||||
{
|
||||
_queuedNodeSizeUpdate = NO;
|
||||
|
||||
[super performBatchUpdates:^{} completion:nil];
|
||||
}
|
||||
|
||||
|
||||
@ -368,7 +368,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
/**
|
||||
* Called just before the view is added to a superview.
|
||||
* Called just before the view is added to a window.
|
||||
*/
|
||||
- (void)willEnterHierarchy ASDISPLAYNODE_REQUIRES_SUPER;
|
||||
|
||||
@ -428,9 +428,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@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.
|
||||
- (nullable ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass;
|
||||
/**
|
||||
* 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.
|
||||
* @param checkViewHierarchy If YES, and no supernode can be found, method will walk up from `self.view` to find a supernode.
|
||||
* If YES, this method must be called on the main thread and the node must not be layer-backed.
|
||||
*/
|
||||
- (nullable ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass checkViewHierarchy:(BOOL)checkViewHierarchy;
|
||||
|
||||
// The two methods below will eventually be exposed, but their names are subject to change.
|
||||
/**
|
||||
|
||||
@ -43,18 +43,28 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node);
|
||||
typedef NS_OPTIONS(NSUInteger, ASInterfaceState)
|
||||
{
|
||||
/** The element is not predicted to be onscreen soon and preloading should not be performed */
|
||||
ASInterfaceStateNone = 1 << 0,
|
||||
ASInterfaceStateNone = 0,
|
||||
/** The element may be added to a view soon that could become visible. Measure the layout, including size calculation. */
|
||||
ASInterfaceStateMeasureLayout = 1 << 1,
|
||||
ASInterfaceStateMeasureLayout = 1 << 0,
|
||||
/** The element is likely enough to come onscreen that disk and/or network data required for display should be fetched. */
|
||||
ASInterfaceStateFetchData = 1 << 2,
|
||||
ASInterfaceStateFetchData = 1 << 1,
|
||||
/** The element is very likely to become visible, and concurrent rendering should be executed for any -setNeedsDisplay. */
|
||||
ASInterfaceStateDisplay = 1 << 3,
|
||||
ASInterfaceStateDisplay = 1 << 2,
|
||||
/** The element is physically onscreen by at least 1 pixel.
|
||||
In practice, all other bit fields should also be set when this flag is set. */
|
||||
ASInterfaceStateVisible = 1 << 4,
|
||||
ASInterfaceStateVisible = 1 << 3,
|
||||
|
||||
/**
|
||||
* The node is not contained in a cell but it is in a window.
|
||||
*
|
||||
* Currently we only set `interfaceState` to other values for
|
||||
* nodes contained in table views or collection views.
|
||||
*/
|
||||
ASInterfaceStateInHierarchy = ASInterfaceStateMeasureLayout | ASInterfaceStateFetchData | ASInterfaceStateDisplay | ASInterfaceStateVisible,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An `ASDisplayNode` is an abstraction over `UIView` and `CALayer` that allows you to perform calculations about a view
|
||||
* hierarchy off the main thread, and could do rendering off the main thread as well.
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASLayout.h"
|
||||
#import "ASLayoutSpec.h"
|
||||
#import "ASCellNode.h"
|
||||
|
||||
@interface ASDisplayNode () <UIGestureRecognizerDelegate>
|
||||
|
||||
@ -1581,6 +1582,10 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(_flags.isEnteringHierarchy, @"You should never call -willEnterHierarchy directly. Appearance is automatically managed by ASDisplayNode");
|
||||
ASDisplayNodeAssert(!_flags.isExitingHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive");
|
||||
|
||||
if (![self supportsInterfaceState]) {
|
||||
self.interfaceState = ASInterfaceStateInHierarchy;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didExitHierarchy
|
||||
@ -1588,6 +1593,10 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(_flags.isExitingHierarchy, @"You should never call -didExitHierarchy directly. Appearance is automatically managed by ASDisplayNode");
|
||||
ASDisplayNodeAssert(!_flags.isEnteringHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive");
|
||||
|
||||
if (![self supportsInterfaceState]) {
|
||||
self.interfaceState = ASInterfaceStateNone;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)clearContents
|
||||
@ -1635,6 +1644,20 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
[self clearFetchedData];
|
||||
}
|
||||
|
||||
/**
|
||||
* We currently only set interface state on nodes
|
||||
* in table/collection views. For other nodes, if they are
|
||||
* in the hierarchy we return `Unknown`, otherwise we return `None`.
|
||||
*
|
||||
* TODO: Avoid traversing up node hierarchy due to possible deadlock.
|
||||
* @see https://github.com/facebook/AsyncDisplayKit/issues/900
|
||||
* Possible solution is to push `isInCellNode` state downward on `addSubnode`/`removeFromSupernode`.
|
||||
*/
|
||||
- (BOOL)supportsInterfaceState {
|
||||
return ([self isKindOfClass:ASCellNode.class]
|
||||
|| [self _supernodeWithClass:ASCellNode.class checkViewHierarchy:NO] != nil);
|
||||
}
|
||||
|
||||
- (ASInterfaceState)interfaceState
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
@ -1643,14 +1666,20 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
|
||||
- (void)setInterfaceState:(ASInterfaceState)interfaceState
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
if (interfaceState != _interfaceState) {
|
||||
if ((interfaceState & ASInterfaceStateMeasureLayout) != (_interfaceState & ASInterfaceStateMeasureLayout)) {
|
||||
ASInterfaceState oldValue;
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
oldValue = _interfaceState;
|
||||
_interfaceState = interfaceState;
|
||||
}
|
||||
|
||||
if (interfaceState != oldValue) {
|
||||
if ((interfaceState & ASInterfaceStateMeasureLayout) != (oldValue & ASInterfaceStateMeasureLayout)) {
|
||||
// Trigger asynchronous measurement if it is not already cached or being calculated.
|
||||
}
|
||||
|
||||
// Entered or exited data loading state.
|
||||
if ((interfaceState & ASInterfaceStateFetchData) != (_interfaceState & ASInterfaceStateFetchData)) {
|
||||
if ((interfaceState & ASInterfaceStateFetchData) != (oldValue & ASInterfaceStateFetchData)) {
|
||||
if (interfaceState & ASInterfaceStateFetchData) {
|
||||
[self fetchData];
|
||||
} else {
|
||||
@ -1659,7 +1688,7 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
}
|
||||
|
||||
// Entered or exited contents rendering state.
|
||||
if ((interfaceState & ASInterfaceStateDisplay) != (_interfaceState & ASInterfaceStateDisplay)) {
|
||||
if ((interfaceState & ASInterfaceStateDisplay) != (oldValue & ASInterfaceStateDisplay)) {
|
||||
if (interfaceState & ASInterfaceStateDisplay) {
|
||||
// Once the working window is eliminated (ASRangeHandlerRender), trigger display directly here.
|
||||
[self setDisplaySuspended:NO];
|
||||
@ -1670,7 +1699,7 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
}
|
||||
|
||||
// Entered or exited data loading state.
|
||||
if ((interfaceState & ASInterfaceStateVisible) != (_interfaceState & ASInterfaceStateVisible)) {
|
||||
if ((interfaceState & ASInterfaceStateVisible) != (oldValue & ASInterfaceStateVisible)) {
|
||||
if (interfaceState & ASInterfaceStateVisible) {
|
||||
// Consider providing a -didBecomeVisible.
|
||||
} else {
|
||||
@ -1678,7 +1707,6 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
}
|
||||
}
|
||||
|
||||
_interfaceState = interfaceState;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1871,7 +1899,7 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
|
||||
// This method has proved helpful in a few rare scenarios, similar to a category extension on UIView, but assumes knowledge of _ASDisplayView.
|
||||
// It's considered private API for now and its use should not be encouraged.
|
||||
- (ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass
|
||||
- (ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass checkViewHierarchy:(BOOL)checkViewHierarchy
|
||||
{
|
||||
ASDisplayNode *supernode = self.supernode;
|
||||
while (supernode) {
|
||||
@ -1879,6 +1907,9 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
return supernode;
|
||||
supernode = supernode.supernode;
|
||||
}
|
||||
if (!checkViewHierarchy) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
UIView *view = self.view.superview;
|
||||
while (view) {
|
||||
|
||||
@ -181,6 +181,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
|
||||
CGFloat _nodesConstrainedWidth;
|
||||
BOOL _ignoreNodesConstrainedWidthChange;
|
||||
BOOL _queuedNodeHeightUpdate;
|
||||
}
|
||||
|
||||
@property (atomic, assign) BOOL asyncDataSourceLocked;
|
||||
@ -908,10 +909,26 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
|
||||
#pragma mark - ASCellNodeLayoutDelegate
|
||||
|
||||
- (void)nodeDidRelayout:(ASCellNode *)node
|
||||
- (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
// Cause UITableView to requery for the new height of this node
|
||||
|
||||
if (!sizeChanged || _queuedNodeHeightUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
_queuedNodeHeightUpdate = YES;
|
||||
[self performSelector:@selector(requeryNodeHeights)
|
||||
withObject:nil
|
||||
afterDelay:0
|
||||
inModes:@[ NSRunLoopCommonModes ]];
|
||||
}
|
||||
|
||||
// Cause UITableView to requery for the new height of this node
|
||||
- (void)requeryNodeHeights
|
||||
{
|
||||
_queuedNodeHeightUpdate = NO;
|
||||
|
||||
[super beginUpdates];
|
||||
[super endUpdates];
|
||||
}
|
||||
|
||||
@ -247,7 +247,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
|
||||
@param attribute The attribute that was tapped. Will not be nil.
|
||||
@param value The value of the tapped attribute.
|
||||
@param point The point within textNode, in textNode's coordinate system, that was touched to trigger a highlight.
|
||||
@discussion If not implemented, the default value is NO.
|
||||
@discussion If not implemented, the default value is YES.
|
||||
@return YES if the entity attribute should be a link, NO otherwise.
|
||||
*/
|
||||
- (BOOL)textNode:(ASTextNode *)textNode shouldHighlightLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point;
|
||||
|
||||
@ -394,13 +394,15 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
|
||||
return [self _linkAttributeValueAtPoint:point
|
||||
attributeName:attributeNameOut
|
||||
range:rangeOut
|
||||
inAdditionalTruncationMessage:NULL];
|
||||
inAdditionalTruncationMessage:NULL
|
||||
forHighlighting:NO];
|
||||
}
|
||||
|
||||
- (id)_linkAttributeValueAtPoint:(CGPoint)point
|
||||
attributeName:(out NSString **)attributeNameOut
|
||||
range:(out NSRange *)rangeOut
|
||||
inAdditionalTruncationMessage:(out BOOL *)inAdditionalTruncationMessageOut
|
||||
forHighlighting:(BOOL)highlighting
|
||||
{
|
||||
ASTextKitRenderer *renderer = [self _renderer];
|
||||
NSRange visibleRange = renderer.visibleRanges[0];
|
||||
@ -453,10 +455,10 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if delegate implements optional method, if not assume NO.
|
||||
// Should the text be highlightable/touchable?
|
||||
if (![_delegate respondsToSelector:@selector(textNode:shouldHighlightLinkAttribute:value:atPoint:)] ||
|
||||
![_delegate textNode:self shouldHighlightLinkAttribute:name value:value atPoint:point]) {
|
||||
// If highlighting, check with delegate first. If not implemented, assume YES.
|
||||
if (highlighting
|
||||
&& [_delegate respondsToSelector:@selector(textNode:shouldHighlightLinkAttribute:value:atPoint:)]
|
||||
&& ![_delegate textNode:self shouldHighlightLinkAttribute:name value:value atPoint:point]) {
|
||||
value = nil;
|
||||
name = nil;
|
||||
}
|
||||
@ -758,7 +760,8 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
|
||||
id linkAttributeValue = [self _linkAttributeValueAtPoint:point
|
||||
attributeName:&linkAttributeName
|
||||
range:&range
|
||||
inAdditionalTruncationMessage:&inAdditionalTruncationMessage];
|
||||
inAdditionalTruncationMessage:&inAdditionalTruncationMessage
|
||||
forHighlighting:YES];
|
||||
|
||||
NSUInteger lastCharIndex = NSIntegerMax;
|
||||
BOOL linkCrossesVisibleRange = (lastCharIndex > range.location) && (lastCharIndex < NSMaxRange(range) - 1);
|
||||
@ -778,11 +781,7 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
|
||||
|
||||
ASDisplayNodeAssertMainThread();
|
||||
|
||||
UITouch *touch = [touches anyObject];
|
||||
|
||||
UIView *view = touch.view;
|
||||
CGPoint point = [touch locationInView:view];
|
||||
point = [self.view convertPoint:point fromView:view];
|
||||
CGPoint point = [[touches anyObject] locationInView:self.view];
|
||||
|
||||
NSRange range = NSMakeRange(0, 0);
|
||||
NSString *linkAttributeName = nil;
|
||||
@ -791,7 +790,8 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
|
||||
id linkAttributeValue = [self _linkAttributeValueAtPoint:point
|
||||
attributeName:&linkAttributeName
|
||||
range:&range
|
||||
inAdditionalTruncationMessage:&inAdditionalTruncationMessage];
|
||||
inAdditionalTruncationMessage:&inAdditionalTruncationMessage
|
||||
forHighlighting:YES];
|
||||
|
||||
NSUInteger lastCharIndex = NSIntegerMax;
|
||||
BOOL linkCrossesVisibleRange = (lastCharIndex > range.location) && (lastCharIndex < NSMaxRange(range) - 1);
|
||||
@ -835,7 +835,20 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
|
||||
{
|
||||
[super touchesMoved:touches withEvent:event];
|
||||
|
||||
[self _clearHighlightIfNecessary];
|
||||
// If touch has moved out of the current highlight range, clear the highlight.
|
||||
if (_highlightRange.length > 0) {
|
||||
NSRange range = NSMakeRange(0, 0);
|
||||
CGPoint point = [[touches anyObject] locationInView:self.view];
|
||||
[self _linkAttributeValueAtPoint:point
|
||||
attributeName:NULL
|
||||
range:&range
|
||||
inAdditionalTruncationMessage:NULL
|
||||
forHighlighting:YES];
|
||||
|
||||
if (!NSEqualRanges(_highlightRange, range)) {
|
||||
[self _clearHighlightIfNecessary];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_handleLongPress:(UILongPressGestureRecognizer *)longPressRecognizer
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
#import "ASDisplayNodeTestsHelper.h"
|
||||
#import "UIView+ASConvenience.h"
|
||||
#import "ASCellNode.h"
|
||||
|
||||
// Conveniences for making nodes named a certain way
|
||||
#define DeclareNodeNamed(n) ASDisplayNode *n = [[ASDisplayNode alloc] init]; n.name = @#n
|
||||
@ -76,11 +77,15 @@ for (ASDisplayNode *n in @[ nodes ]) {\
|
||||
+ (dispatch_queue_t)asyncSizingQueue;
|
||||
- (id)initWithViewClass:(Class)viewClass;
|
||||
- (id)initWithLayerClass:(Class)layerClass;
|
||||
|
||||
// FIXME: Importing ASDisplayNodeInternal.h causes a heap of problems.
|
||||
- (void)enterInterfaceState:(ASInterfaceState)interfaceState;
|
||||
@end
|
||||
|
||||
@interface ASTestDisplayNode : ASDisplayNode
|
||||
@property (atomic, copy) void (^willDeallocBlock)(ASTestDisplayNode *node);
|
||||
@property (atomic, copy) CGSize(^calculateSizeBlock)(ASTestDisplayNode *node, CGSize size);
|
||||
@property (atomic) BOOL hasFetchedData;
|
||||
@end
|
||||
|
||||
@interface ASTestResponderNode : ASTestDisplayNode
|
||||
@ -93,6 +98,18 @@ for (ASDisplayNode *n in @[ nodes ]) {\
|
||||
return _calculateSizeBlock ? _calculateSizeBlock(self, constrainedSize) : CGSizeZero;
|
||||
}
|
||||
|
||||
- (void)fetchData
|
||||
{
|
||||
[super fetchData];
|
||||
self.hasFetchedData = YES;
|
||||
}
|
||||
|
||||
- (void)clearFetchedData
|
||||
{
|
||||
[super clearFetchedData];
|
||||
self.hasFetchedData = NO;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (_willDeallocBlock) {
|
||||
@ -1666,6 +1683,48 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point
|
||||
[self checkBackgroundColorOpaqueRelationshipWithViewLoaded:NO layerBacked:YES];
|
||||
}
|
||||
|
||||
// Check that nodes who have no cell node (no range controller)
|
||||
// do get their `fetchData` called, and they do report
|
||||
// the fetch data interface state.
|
||||
- (void)testInterfaceStateForNonCellNode
|
||||
{
|
||||
ASTestWindow *window = [ASTestWindow new];
|
||||
ASTestDisplayNode *node = [ASTestDisplayNode new];
|
||||
XCTAssert(node.interfaceState == ASInterfaceStateNone);
|
||||
XCTAssert(!node.hasFetchedData);
|
||||
|
||||
[window addSubview:node.view];
|
||||
XCTAssert(node.hasFetchedData);
|
||||
XCTAssert(node.interfaceState == ASInterfaceStateInHierarchy);
|
||||
|
||||
[node.view removeFromSuperview];
|
||||
XCTAssert(!node.hasFetchedData);
|
||||
XCTAssert(node.interfaceState == ASInterfaceStateNone);
|
||||
}
|
||||
|
||||
// Check that nodes who have no cell node (no range controller)
|
||||
// do get their `fetchData` called, and they do report
|
||||
// the fetch data interface state.
|
||||
- (void)testInterfaceStateForCellNode
|
||||
{
|
||||
ASCellNode *cellNode = [ASCellNode new];
|
||||
ASTestDisplayNode *node = [ASTestDisplayNode new];
|
||||
XCTAssert(node.interfaceState == ASInterfaceStateNone);
|
||||
XCTAssert(!node.hasFetchedData);
|
||||
|
||||
// Simulate range handler updating cell node.
|
||||
[cellNode addSubnode:node];
|
||||
[cellNode enterInterfaceState:ASInterfaceStateFetchData];
|
||||
XCTAssert(node.hasFetchedData);
|
||||
XCTAssert(node.interfaceState == ASInterfaceStateFetchData);
|
||||
|
||||
// If the node goes into a view it should not adopt the `InHierarchy` state.
|
||||
ASTestWindow *window = [ASTestWindow new];
|
||||
[window addSubview:cellNode.view];
|
||||
XCTAssert(node.hasFetchedData);
|
||||
XCTAssert(node.interfaceState == ASInterfaceStateFetchData);
|
||||
}
|
||||
|
||||
- (void)testInitWithViewClass
|
||||
{
|
||||
ASDisplayNode *scrollNode = [[ASDisplayNode alloc] initWithViewClass:[UIScrollView class]];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user