mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-10 16:29:55 +00:00
Lay some foundation for our new pending state controller
This commit is contained in:
parent
d899f12f70
commit
99b674c346
@ -455,6 +455,16 @@
|
||||
B350625F1B0111800018CF92 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AF195D04C000B7D73C /* Foundation.framework */; };
|
||||
C78F7E2A1BF7808300CDEAFC /* ASTableNode.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F880591BEAEC7500D17647 /* ASTableNode.m */; };
|
||||
C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
CC3B20831C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; };
|
||||
CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; };
|
||||
CC3B20851C3F76D600798563 /* ASPendingStateController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20821C3F76D600798563 /* ASPendingStateController.mm */; };
|
||||
CC3B20861C3F76D600798563 /* ASPendingStateController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20821C3F76D600798563 /* ASPendingStateController.mm */; };
|
||||
CC3B20891C3F7A5400798563 /* ASWeakSet.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20871C3F7A5400798563 /* ASWeakSet.h */; };
|
||||
CC3B208A1C3F7A5400798563 /* ASWeakSet.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20871C3F7A5400798563 /* ASWeakSet.h */; };
|
||||
CC3B208B1C3F7A5400798563 /* ASWeakSet.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20881C3F7A5400798563 /* ASWeakSet.m */; };
|
||||
CC3B208C1C3F7A5400798563 /* ASWeakSet.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20881C3F7A5400798563 /* ASWeakSet.m */; };
|
||||
CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.m */; };
|
||||
CC3B20901C3F892D00798563 /* ASPendingStateControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B208F1C3F892D00798563 /* ASPendingStateControllerTests.m */; };
|
||||
CC7FD9DE1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */; };
|
||||
CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */; };
|
||||
@ -786,6 +796,12 @@
|
||||
B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASLayoutManager.m; path = TextKit/ASLayoutManager.m; sourceTree = "<group>"; };
|
||||
B35061DA1B010EDF0018CF92 /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AsyncDisplayKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B35061DD1B010EDF0018CF92 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../AsyncDisplayKit-iOS/Info.plist"; sourceTree = "<group>"; };
|
||||
CC3B20811C3F76D600798563 /* ASPendingStateController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPendingStateController.h; sourceTree = "<group>"; };
|
||||
CC3B20821C3F76D600798563 /* ASPendingStateController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPendingStateController.mm; sourceTree = "<group>"; };
|
||||
CC3B20871C3F7A5400798563 /* ASWeakSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASWeakSet.h; sourceTree = "<group>"; };
|
||||
CC3B20881C3F7A5400798563 /* ASWeakSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakSet.m; sourceTree = "<group>"; };
|
||||
CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakSetTests.m; sourceTree = "<group>"; };
|
||||
CC3B208F1C3F892D00798563 /* ASPendingStateControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPendingStateControllerTests.m; sourceTree = "<group>"; };
|
||||
CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPhotosFrameworkImageRequest.h; sourceTree = "<group>"; };
|
||||
CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequest.m; sourceTree = "<group>"; };
|
||||
CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequestTests.m; sourceTree = "<group>"; };
|
||||
@ -1002,6 +1018,8 @@
|
||||
children = (
|
||||
DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.m */,
|
||||
DBC452DD1C5C6A6A00B16017 /* ArrayDiffingTests.m */,
|
||||
CC3B208F1C3F892D00798563 /* ASPendingStateControllerTests.m */,
|
||||
CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.m */,
|
||||
057D02C01AC0A66700C7AC3C /* AsyncDisplayKitTestHost */,
|
||||
056D21501ABCEDA1001107EF /* ASSnapshotTestCase.h */,
|
||||
05EA6FE61AC0966E00E35788 /* ASSnapshotTestCase.mm */,
|
||||
@ -1123,6 +1141,10 @@
|
||||
children = (
|
||||
DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */,
|
||||
DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.m */,
|
||||
CC3B20811C3F76D600798563 /* ASPendingStateController.h */,
|
||||
CC3B20821C3F76D600798563 /* ASPendingStateController.mm */,
|
||||
CC3B20871C3F7A5400798563 /* ASWeakSet.h */,
|
||||
CC3B20881C3F7A5400798563 /* ASWeakSet.m */,
|
||||
AC026B6D1BD57DBF00BBC17E /* _ASHierarchyChangeSet.h */,
|
||||
AC026B6E1BD57DBF00BBC17E /* _ASHierarchyChangeSet.m */,
|
||||
9C65A7291BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h */,
|
||||
@ -1413,6 +1435,7 @@
|
||||
257754B51BEE44CD00737CA5 /* ASTextKitTruncating.h in Headers */,
|
||||
ACF6ED4F1B17847A00DA7C62 /* ASStackPositionedLayout.h in Headers */,
|
||||
257754A71BEE44CD00737CA5 /* ASTextKitAttributes.h in Headers */,
|
||||
CC3B20891C3F7A5400798563 /* ASWeakSet.h in Headers */,
|
||||
ACF6ED511B17847A00DA7C62 /* ASStackUnpositionedLayout.h in Headers */,
|
||||
9C6BB3B21B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */,
|
||||
ACF6ED311B17843500DA7C62 /* ASStaticLayoutSpec.h in Headers */,
|
||||
@ -1421,6 +1444,7 @@
|
||||
257754C11BEE458E00737CA5 /* ASTextKitHelpers.h in Headers */,
|
||||
B30BF6521C5964B0004FCD53 /* ASLayoutManager.h in Headers */,
|
||||
0574D5E219C110940097DC25 /* ASTableViewProtocols.h in Headers */,
|
||||
CC3B20831C3F76D600798563 /* ASPendingStateController.h in Headers */,
|
||||
058D0A51195D05CB00B7D73C /* ASTextNode.h in Headers */,
|
||||
058D0A81195D05F900B7D73C /* ASThread.h in Headers */,
|
||||
ACC945A91BA9E7A0005E1FB8 /* ASViewController.h in Headers */,
|
||||
@ -1475,6 +1499,7 @@
|
||||
B35061F51B010EFD0018CF92 /* ASCollectionView.h in Headers */,
|
||||
254C6B791BF94DF4003EC431 /* ASTextKitEntityAttribute.h in Headers */,
|
||||
509E68631B3AEDB4009B9150 /* ASCollectionViewLayoutController.h in Headers */,
|
||||
CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */,
|
||||
B35061F71B010EFD0018CF92 /* ASCollectionViewProtocols.h in Headers */,
|
||||
DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */,
|
||||
B35061FA1B010EFD0018CF92 /* ASControlNode+Subclasses.h in Headers */,
|
||||
@ -1517,6 +1542,7 @@
|
||||
34EFC7791B701D3600AD841F /* ASLayoutSpecUtilities.h in Headers */,
|
||||
B350625C1B010F070018CF92 /* ASLog.h in Headers */,
|
||||
0442850E1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.h in Headers */,
|
||||
CC3B208A1C3F7A5400798563 /* ASWeakSet.h in Headers */,
|
||||
DE8BEAC21C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */,
|
||||
B35062041B010EFD0018CF92 /* ASMultiplexImageNode.h in Headers */,
|
||||
DECBD6E81BE56E1900CF4905 /* ASButtonNode.h in Headers */,
|
||||
@ -1611,6 +1637,7 @@
|
||||
058D09B9195D04C000B7D73C /* Frameworks */,
|
||||
058D09BA195D04C000B7D73C /* Resources */,
|
||||
3B9D88CDF51B429C8409E4B6 /* Copy Pods Resources */,
|
||||
78B4649EC16385BFAFD84D49 /* Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@ -1740,6 +1767,21 @@
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
78B4649EC16385BFAFD84D49 /* Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@ -1799,6 +1841,7 @@
|
||||
257754C41BEE458E00737CA5 /* ASTextNodeWordKerner.m in Sources */,
|
||||
058D0A1A195D050800B7D73C /* ASHighlightOverlayLayer.mm in Sources */,
|
||||
058D0A2B195D050800B7D73C /* ASImageNode+CGExtras.m in Sources */,
|
||||
CC3B208B1C3F7A5400798563 /* ASWeakSet.m in Sources */,
|
||||
058D0A16195D050800B7D73C /* ASImageNode.mm in Sources */,
|
||||
430E7C911B4C23F100697A4C /* ASIndexPath.m in Sources */,
|
||||
ACF6ED231B17843500DA7C62 /* ASInsetLayoutSpec.mm in Sources */,
|
||||
@ -1815,6 +1858,7 @@
|
||||
058D0A1B195D050800B7D73C /* ASMutableAttributedStringBuilder.m in Sources */,
|
||||
055B9FA91A1C154B00035D6D /* ASNetworkImageNode.mm in Sources */,
|
||||
AEB7B01B1C5962EA00662EF4 /* ASDefaultPlayButton.m in Sources */,
|
||||
CC3B20851C3F76D600798563 /* ASPendingStateController.mm in Sources */,
|
||||
ACF6ED2C1B17843500DA7C62 /* ASOverlayLayoutSpec.mm in Sources */,
|
||||
0442850F1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm in Sources */,
|
||||
257754921BED28F300737CA5 /* ASEqualityHashHelpers.mm in Sources */,
|
||||
@ -1861,6 +1905,7 @@
|
||||
ACF6ED5C1B178DC700DA7C62 /* ASCenterLayoutSpecSnapshotTests.mm in Sources */,
|
||||
9F06E5CD1B4CAF4200F015D8 /* ASCollectionViewTests.m in Sources */,
|
||||
2911485C1A77147A005D0878 /* ASControlNodeTests.m in Sources */,
|
||||
CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.m in Sources */,
|
||||
ACF6ED5D1B178DC700DA7C62 /* ASDimensionTests.mm in Sources */,
|
||||
058D0A38195D057000B7D73C /* ASDisplayLayerTests.m in Sources */,
|
||||
2538B6F31BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m in Sources */,
|
||||
@ -1883,6 +1928,7 @@
|
||||
AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.m in Sources */,
|
||||
254C6B521BF8FE6D003EC431 /* ASTextKitTruncationTests.mm in Sources */,
|
||||
058D0A3D195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.m in Sources */,
|
||||
CC3B20901C3F892D00798563 /* ASPendingStateControllerTests.m in Sources */,
|
||||
058D0A40195D057000B7D73C /* ASTextNodeTests.m in Sources */,
|
||||
DBC453221C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.m in Sources */,
|
||||
058D0A41195D057000B7D73C /* ASTextNodeWordKernerTests.mm in Sources */,
|
||||
@ -1936,6 +1982,7 @@
|
||||
B35061FF1B010EFD0018CF92 /* ASDisplayNodeExtras.mm in Sources */,
|
||||
B35062011B010EFD0018CF92 /* ASEditableTextNode.mm in Sources */,
|
||||
254C6B881BF94F8A003EC431 /* ASTextKitRenderer.mm in Sources */,
|
||||
CC3B208C1C3F7A5400798563 /* ASWeakSet.m in Sources */,
|
||||
B350621C1B010EFD0018CF92 /* ASFlowLayoutController.mm in Sources */,
|
||||
B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */,
|
||||
B35062541B010EFD0018CF92 /* ASImageNode+CGExtras.m in Sources */,
|
||||
@ -1950,6 +1997,7 @@
|
||||
DECBD6EA1BE56E1900CF4905 /* ASButtonNode.mm in Sources */,
|
||||
254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.m in Sources */,
|
||||
34EFC76B1B701CEB00AD841F /* ASLayoutSpec.mm in Sources */,
|
||||
CC3B20861C3F76D600798563 /* ASPendingStateController.mm in Sources */,
|
||||
254C6B8C1BF94F8A003EC431 /* ASTextKitTailTruncater.mm in Sources */,
|
||||
B35062051B010EFD0018CF92 /* ASMultiplexImageNode.mm in Sources */,
|
||||
B35062251B010EFD0018CF92 /* ASMutableAttributedStringBuilder.m in Sources */,
|
||||
|
||||
@ -981,6 +981,17 @@ static inline void filterNodesInLayoutAtIndexesWithIntersectingNodes(
|
||||
_contentsScaleForDisplay = contentsScaleForDisplay;
|
||||
}
|
||||
|
||||
- (void)applyPendingViewState
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (self.layerBacked) {
|
||||
[_pendingViewState applyToLayer:self.layer];
|
||||
} else {
|
||||
[_pendingViewState applyToView:self.view];
|
||||
}
|
||||
[_pendingViewState clearChanges];
|
||||
}
|
||||
|
||||
- (void)displayImmediately
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
@ -2366,13 +2377,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
// for the view/layer are still valid.
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
|
||||
if (_flags.layerBacked) {
|
||||
[_pendingViewState applyToLayer:_layer];
|
||||
} else {
|
||||
[_pendingViewState applyToView:_view];
|
||||
}
|
||||
|
||||
_pendingViewState = nil;
|
||||
[self applyPendingViewState];
|
||||
|
||||
// TODO: move this into real pending state
|
||||
if (_flags.displaySuspended) {
|
||||
|
||||
@ -178,6 +178,8 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
|
||||
|
||||
@property (nonatomic, assign) CGFloat contentsScaleForDisplay;
|
||||
|
||||
- (void)applyPendingViewState;
|
||||
|
||||
/**
|
||||
* // TODO: NOT YET IMPLEMENTED
|
||||
*
|
||||
|
||||
45
AsyncDisplayKit/Private/ASPendingStateController.h
Normal file
45
AsyncDisplayKit/Private/ASPendingStateController.h
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// ASPendingStateController.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 1/7/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class ASDisplayNode;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
A singleton that is responsible for applying changes to
|
||||
UIView/CALayer properties of display nodes when they
|
||||
have been set on background threads.
|
||||
|
||||
This controller will enqueue run-loop events to flush changes
|
||||
but if you need
|
||||
*/
|
||||
@interface ASPendingStateController : NSObject
|
||||
|
||||
+ (ASPendingStateController *)sharedInstance;
|
||||
|
||||
@property (nonatomic, readonly) BOOL hasChanges;
|
||||
|
||||
/**
|
||||
Flush all pending states for nodes now. Any UIView/CALayer properties
|
||||
that have been set in the background will be applied to their
|
||||
corresponding views/layers before this method returns.
|
||||
|
||||
You must call this method on the main thread.
|
||||
*/
|
||||
- (void)flush;
|
||||
|
||||
/**
|
||||
Register this node as having pending state that needs
|
||||
*/
|
||||
- (void)registerNode:(ASDisplayNode *)node;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
99
AsyncDisplayKit/Private/ASPendingStateController.mm
Normal file
99
AsyncDisplayKit/Private/ASPendingStateController.mm
Normal file
@ -0,0 +1,99 @@
|
||||
//
|
||||
// ASPendingStateController.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 1/7/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASPendingStateController.h"
|
||||
#import "ASThread.h"
|
||||
#import "ASWeakSet.h"
|
||||
#import "ASDisplayNode.h"
|
||||
|
||||
@interface ASPendingStateController()
|
||||
{
|
||||
ASDN::Mutex _lock;
|
||||
|
||||
struct ASPendingStateControllerFlags {
|
||||
unsigned pendingFlush:1;
|
||||
} _flags;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong, readonly) ASWeakSet<ASDisplayNode *> *dirtyNodes;
|
||||
@end
|
||||
|
||||
@implementation ASPendingStateController
|
||||
|
||||
#pragma mark Lifecycle & Singleton
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_dirtyNodes = [ASWeakSet new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (ASPendingStateController *)sharedInstance
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
static ASPendingStateController *controller;
|
||||
dispatch_once(&onceToken, ^{
|
||||
controller = [ASPendingStateController new];
|
||||
});
|
||||
return controller;
|
||||
}
|
||||
|
||||
#pragma mark External API
|
||||
|
||||
- (void)flush
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self flushNow];
|
||||
}
|
||||
|
||||
- (void)registerNode:(ASDisplayNode *)node
|
||||
{
|
||||
ASDN::MutexLocker l(_lock);
|
||||
[_dirtyNodes addObject:node];
|
||||
|
||||
[self scheduleFlushIfNeeded];
|
||||
}
|
||||
|
||||
#pragma mark Private Methods
|
||||
|
||||
/**
|
||||
This method is assumed to be called with the lock held.
|
||||
*/
|
||||
- (void)scheduleFlushIfNeeded
|
||||
{
|
||||
if (_flags.pendingFlush) {
|
||||
return;
|
||||
}
|
||||
|
||||
_flags.pendingFlush = YES;
|
||||
[self performSelectorOnMainThread:@selector(flushNow) withObject:nil waitUntilDone:NO modes:@[ NSRunLoopCommonModes ]];
|
||||
}
|
||||
|
||||
- (void)flushNow
|
||||
{
|
||||
ASDN::MutexLocker l(_lock);
|
||||
for (__unused ASDisplayNode *node in _dirtyNodes) {
|
||||
// TODO: apply pending state.
|
||||
}
|
||||
[_dirtyNodes removeAllObjects];
|
||||
_flags.pendingFlush = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASPendingStateController (Testing)
|
||||
|
||||
- (BOOL)test_isFlushScheduled
|
||||
{
|
||||
return _flags.pendingFlush;
|
||||
}
|
||||
|
||||
@end
|
||||
40
AsyncDisplayKit/Private/ASWeakSet.h
Normal file
40
AsyncDisplayKit/Private/ASWeakSet.h
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// ASWeakSet.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 1/7/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface ASWeakSet<__covariant ObjectType> : NSObject<NSFastEnumeration>
|
||||
|
||||
/// Returns YES if the receiver is empty, NO otherwise.
|
||||
@property (nonatomic, readonly, getter=isEmpty) BOOL empty;
|
||||
|
||||
/// Returns YES if `object` is in the receiver, NO otherwise.
|
||||
- (BOOL)containsObject:(ObjectType)object;
|
||||
|
||||
/// Insets `object` into the set.
|
||||
- (void)addObject:(ObjectType)object;
|
||||
|
||||
/// Removes object from the set.
|
||||
- (void)removeObject:(ObjectType)object;
|
||||
|
||||
/// Removes all objects from the set.
|
||||
- (void)removeAllObjects;
|
||||
|
||||
/**
|
||||
How many objects are contained in this set.
|
||||
|
||||
NOTE: This method is O(N). Consider using the `empty`
|
||||
property.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger count;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
68
AsyncDisplayKit/Private/ASWeakSet.m
Normal file
68
AsyncDisplayKit/Private/ASWeakSet.m
Normal file
@ -0,0 +1,68 @@
|
||||
//
|
||||
// ASWeakSet.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 1/7/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASWeakSet.h"
|
||||
|
||||
@interface ASWeakSet<__covariant ObjectType> ()
|
||||
@property (nonatomic, strong, readonly) NSMapTable<NSNull *, NSNull *> *mapTable;
|
||||
@end
|
||||
|
||||
@implementation ASWeakSet
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_mapTable = [NSMapTable weakToStrongObjectsMapTable];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)addObject:(id)object
|
||||
{
|
||||
[_mapTable setObject:[NSNull null] forKey:object];
|
||||
}
|
||||
|
||||
- (void)removeObject:(id)object
|
||||
{
|
||||
[_mapTable removeObjectForKey:object];
|
||||
}
|
||||
|
||||
- (void)removeAllObjects
|
||||
{
|
||||
[_mapTable removeAllObjects];
|
||||
}
|
||||
|
||||
- (BOOL)containsObject:(id)object
|
||||
{
|
||||
return [_mapTable objectForKey:object] != nil;
|
||||
}
|
||||
|
||||
- (BOOL)isEmpty
|
||||
{
|
||||
for (__unused id object in _mapTable) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSUInteger)count
|
||||
{
|
||||
NSInteger count = 0;
|
||||
for (__unused id object in _mapTable) {
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id _Nonnull *)buffer count:(NSUInteger)len
|
||||
{
|
||||
return [_mapTable countByEnumeratingWithState:state objects:buffer count:len];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -30,4 +30,8 @@
|
||||
+ (_ASPendingState *)pendingViewStateFromLayer:(CALayer *)layer;
|
||||
+ (_ASPendingState *)pendingViewStateFromView:(UIView *)view;
|
||||
|
||||
@property (nonatomic, readonly) BOOL hasChanges;
|
||||
|
||||
- (void)clearChanges;
|
||||
|
||||
@end
|
||||
|
||||
@ -12,6 +12,57 @@
|
||||
#import "_ASAsyncTransactionContainer.h"
|
||||
#import "ASAssert.h"
|
||||
|
||||
typedef struct {
|
||||
// Properties
|
||||
int needsDisplay:1;
|
||||
int needsLayout:1;
|
||||
|
||||
// Flags indicating that a given property should be applied to the view at creation
|
||||
int setClipsToBounds:1;
|
||||
int setOpaque:1;
|
||||
int setNeedsDisplayOnBoundsChange:1;
|
||||
int setAutoresizesSubviews:1;
|
||||
int setAutoresizingMask:1;
|
||||
int setFrame:1;
|
||||
int setBounds:1;
|
||||
int setBackgroundColor:1;
|
||||
int setTintColor:1;
|
||||
int setContents:1;
|
||||
int setHidden:1;
|
||||
int setAlpha:1;
|
||||
int setCornerRadius:1;
|
||||
int setContentMode:1;
|
||||
int setNeedsDisplay:1;
|
||||
int setAnchorPoint:1;
|
||||
int setPosition:1;
|
||||
int setZPosition:1;
|
||||
int setContentsScale:1;
|
||||
int setTransform:1;
|
||||
int setSublayerTransform:1;
|
||||
int setUserInteractionEnabled:1;
|
||||
int setExclusiveTouch:1;
|
||||
int setShadowColor:1;
|
||||
int setShadowOpacity:1;
|
||||
int setShadowOffset:1;
|
||||
int setShadowRadius:1;
|
||||
int setBorderWidth:1;
|
||||
int setBorderColor:1;
|
||||
int setAsyncTransactionContainer:1;
|
||||
int setAllowsEdgeAntialiasing:1;
|
||||
int setEdgeAntialiasingMask:1;
|
||||
int setIsAccessibilityElement:1;
|
||||
int setAccessibilityLabel:1;
|
||||
int setAccessibilityHint:1;
|
||||
int setAccessibilityValue:1;
|
||||
int setAccessibilityTraits:1;
|
||||
int setAccessibilityFrame:1;
|
||||
int setAccessibilityLanguage:1;
|
||||
int setAccessibilityElementsHidden:1;
|
||||
int setAccessibilityViewIsModal:1;
|
||||
int setShouldGroupAccessibilityChildren:1;
|
||||
int setAccessibilityIdentifier:1;
|
||||
} ASPendingStateFlags;
|
||||
|
||||
@implementation _ASPendingState
|
||||
{
|
||||
@package //Expose all ivars for ASDisplayNode to bypass getters for efficiency
|
||||
@ -50,56 +101,7 @@
|
||||
BOOL shouldGroupAccessibilityChildren;
|
||||
NSString *accessibilityIdentifier;
|
||||
|
||||
struct {
|
||||
// Properties
|
||||
int needsDisplay:1;
|
||||
int needsLayout:1;
|
||||
|
||||
// Flags indicating that a given property should be applied to the view at creation
|
||||
int setClipsToBounds:1;
|
||||
int setOpaque:1;
|
||||
int setNeedsDisplayOnBoundsChange:1;
|
||||
int setAutoresizesSubviews:1;
|
||||
int setAutoresizingMask:1;
|
||||
int setFrame:1;
|
||||
int setBounds:1;
|
||||
int setBackgroundColor:1;
|
||||
int setTintColor:1;
|
||||
int setContents:1;
|
||||
int setHidden:1;
|
||||
int setAlpha:1;
|
||||
int setCornerRadius:1;
|
||||
int setContentMode:1;
|
||||
int setNeedsDisplay:1;
|
||||
int setAnchorPoint:1;
|
||||
int setPosition:1;
|
||||
int setZPosition:1;
|
||||
int setContentsScale:1;
|
||||
int setTransform:1;
|
||||
int setSublayerTransform:1;
|
||||
int setUserInteractionEnabled:1;
|
||||
int setExclusiveTouch:1;
|
||||
int setShadowColor:1;
|
||||
int setShadowOpacity:1;
|
||||
int setShadowOffset:1;
|
||||
int setShadowRadius:1;
|
||||
int setBorderWidth:1;
|
||||
int setBorderColor:1;
|
||||
int setAsyncTransactionContainer:1;
|
||||
int setAllowsEdgeAntialiasing:1;
|
||||
int setEdgeAntialiasingMask:1;
|
||||
int setIsAccessibilityElement:1;
|
||||
int setAccessibilityLabel:1;
|
||||
int setAccessibilityHint:1;
|
||||
int setAccessibilityValue:1;
|
||||
int setAccessibilityTraits:1;
|
||||
int setAccessibilityFrame:1;
|
||||
int setAccessibilityLanguage:1;
|
||||
int setAccessibilityElementsHidden:1;
|
||||
int setAccessibilityViewIsModal:1;
|
||||
int setShouldGroupAccessibilityChildren:1;
|
||||
int setAccessibilityIdentifier:1;
|
||||
} _flags;
|
||||
ASPendingStateFlags _flags;
|
||||
}
|
||||
|
||||
|
||||
@ -199,12 +201,6 @@ static UIColor *defaultTintColor = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CALayer *)layer
|
||||
{
|
||||
ASDisplayNodeAssert(NO, @"One shouldn't call node.layer when the view isn't loaded, but we're returning nil to not crash if someone is still doing this");
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setNeedsDisplay
|
||||
{
|
||||
_flags.needsDisplay = YES;
|
||||
@ -560,91 +556,92 @@ static UIColor *defaultTintColor = nil;
|
||||
|
||||
- (void)applyToLayer:(CALayer *)layer
|
||||
{
|
||||
if (_flags.setAnchorPoint)
|
||||
ASPendingStateFlags flags = _flags;
|
||||
if (flags.setAnchorPoint)
|
||||
layer.anchorPoint = anchorPoint;
|
||||
|
||||
if (_flags.setPosition)
|
||||
if (flags.setPosition)
|
||||
layer.position = position;
|
||||
|
||||
if (_flags.setZPosition)
|
||||
if (flags.setZPosition)
|
||||
layer.zPosition = zPosition;
|
||||
|
||||
if (_flags.setBounds)
|
||||
if (flags.setBounds)
|
||||
layer.bounds = bounds;
|
||||
|
||||
if (_flags.setContentsScale)
|
||||
if (flags.setContentsScale)
|
||||
layer.contentsScale = contentsScale;
|
||||
|
||||
if (_flags.setTransform)
|
||||
if (flags.setTransform)
|
||||
layer.transform = transform;
|
||||
|
||||
if (_flags.setSublayerTransform)
|
||||
if (flags.setSublayerTransform)
|
||||
layer.sublayerTransform = sublayerTransform;
|
||||
|
||||
if (_flags.setContents)
|
||||
if (flags.setContents)
|
||||
layer.contents = contents;
|
||||
|
||||
if (_flags.setClipsToBounds)
|
||||
if (flags.setClipsToBounds)
|
||||
layer.masksToBounds = clipsToBounds;
|
||||
|
||||
if (_flags.setBackgroundColor)
|
||||
if (flags.setBackgroundColor)
|
||||
layer.backgroundColor = backgroundColor;
|
||||
|
||||
if (_flags.setOpaque)
|
||||
if (flags.setOpaque)
|
||||
layer.opaque = opaque;
|
||||
|
||||
if (_flags.setHidden)
|
||||
if (flags.setHidden)
|
||||
layer.hidden = isHidden;
|
||||
|
||||
if (_flags.setAlpha)
|
||||
if (flags.setAlpha)
|
||||
layer.opacity = alpha;
|
||||
|
||||
if (_flags.setCornerRadius)
|
||||
if (flags.setCornerRadius)
|
||||
layer.cornerRadius = cornerRadius;
|
||||
|
||||
if (_flags.setContentMode)
|
||||
if (flags.setContentMode)
|
||||
layer.contentsGravity = ASDisplayNodeCAContentsGravityFromUIContentMode(contentMode);
|
||||
|
||||
if (_flags.setShadowColor)
|
||||
if (flags.setShadowColor)
|
||||
layer.shadowColor = shadowColor;
|
||||
|
||||
if (_flags.setShadowOpacity)
|
||||
if (flags.setShadowOpacity)
|
||||
layer.shadowOpacity = shadowOpacity;
|
||||
|
||||
if (_flags.setShadowOffset)
|
||||
if (flags.setShadowOffset)
|
||||
layer.shadowOffset = shadowOffset;
|
||||
|
||||
if (_flags.setShadowRadius)
|
||||
if (flags.setShadowRadius)
|
||||
layer.shadowRadius = shadowRadius;
|
||||
|
||||
if (_flags.setBorderWidth)
|
||||
if (flags.setBorderWidth)
|
||||
layer.borderWidth = borderWidth;
|
||||
|
||||
if (_flags.setBorderColor)
|
||||
if (flags.setBorderColor)
|
||||
layer.borderColor = borderColor;
|
||||
|
||||
if (_flags.setNeedsDisplayOnBoundsChange)
|
||||
if (flags.setNeedsDisplayOnBoundsChange)
|
||||
layer.needsDisplayOnBoundsChange = needsDisplayOnBoundsChange;
|
||||
|
||||
if (_flags.setAllowsEdgeAntialiasing)
|
||||
if (flags.setAllowsEdgeAntialiasing)
|
||||
layer.allowsEdgeAntialiasing = allowsEdgeAntialiasing;
|
||||
|
||||
if (_flags.setEdgeAntialiasingMask)
|
||||
if (flags.setEdgeAntialiasingMask)
|
||||
layer.edgeAntialiasingMask = edgeAntialiasingMask;
|
||||
|
||||
if (_flags.needsDisplay)
|
||||
if (flags.needsDisplay)
|
||||
[layer setNeedsDisplay];
|
||||
|
||||
if (_flags.needsLayout)
|
||||
if (flags.needsLayout)
|
||||
[layer setNeedsLayout];
|
||||
|
||||
if (_flags.setAsyncTransactionContainer)
|
||||
if (flags.setAsyncTransactionContainer)
|
||||
layer.asyncdisplaykit_asyncTransactionContainer = asyncTransactionContainer;
|
||||
|
||||
if (_flags.setOpaque)
|
||||
if (flags.setOpaque)
|
||||
ASDisplayNodeAssert(layer.opaque == opaque, @"Didn't set opaque as desired");
|
||||
|
||||
if (_flags.setFrame)
|
||||
if (flags.setFrame)
|
||||
ASDisplayNodeAssert(NO, @"Frame property should only be used for synchronously wrapped nodes. See setFrame: in ASDisplayNode+UIViewBridge");
|
||||
}
|
||||
|
||||
@ -660,143 +657,144 @@ static UIColor *defaultTintColor = nil;
|
||||
|
||||
CALayer *layer = view.layer;
|
||||
|
||||
if (_flags.setAnchorPoint)
|
||||
ASPendingStateFlags flags = _flags;
|
||||
if (flags.setAnchorPoint)
|
||||
layer.anchorPoint = anchorPoint;
|
||||
|
||||
if (_flags.setPosition)
|
||||
if (flags.setPosition)
|
||||
layer.position = position;
|
||||
|
||||
if (_flags.setZPosition)
|
||||
if (flags.setZPosition)
|
||||
layer.zPosition = zPosition;
|
||||
|
||||
// This should only be used for synchronous views wrapped by nodes.
|
||||
if (_flags.setFrame && !(_flags.setBounds && _flags.setPosition)) {
|
||||
if (flags.setFrame && !(flags.setBounds && flags.setPosition)) {
|
||||
view.frame = frame;
|
||||
}
|
||||
|
||||
if (_flags.setBounds)
|
||||
if (flags.setBounds)
|
||||
view.bounds = bounds;
|
||||
|
||||
if (_flags.setContentsScale)
|
||||
if (flags.setContentsScale)
|
||||
layer.contentsScale = contentsScale;
|
||||
|
||||
if (_flags.setTransform)
|
||||
if (flags.setTransform)
|
||||
layer.transform = transform;
|
||||
|
||||
if (_flags.setSublayerTransform)
|
||||
if (flags.setSublayerTransform)
|
||||
layer.sublayerTransform = sublayerTransform;
|
||||
|
||||
if (_flags.setContents)
|
||||
if (flags.setContents)
|
||||
layer.contents = contents;
|
||||
|
||||
if (_flags.setClipsToBounds)
|
||||
if (flags.setClipsToBounds)
|
||||
view.clipsToBounds = clipsToBounds;
|
||||
|
||||
if (_flags.setBackgroundColor)
|
||||
if (flags.setBackgroundColor)
|
||||
layer.backgroundColor = backgroundColor;
|
||||
|
||||
if (_flags.setTintColor)
|
||||
if (flags.setTintColor)
|
||||
view.tintColor = self.tintColor;
|
||||
|
||||
if (_flags.setOpaque)
|
||||
if (flags.setOpaque)
|
||||
view.layer.opaque = opaque;
|
||||
|
||||
if (_flags.setHidden)
|
||||
if (flags.setHidden)
|
||||
view.hidden = isHidden;
|
||||
|
||||
if (_flags.setAlpha)
|
||||
if (flags.setAlpha)
|
||||
view.alpha = alpha;
|
||||
|
||||
if (_flags.setCornerRadius)
|
||||
if (flags.setCornerRadius)
|
||||
layer.cornerRadius = cornerRadius;
|
||||
|
||||
if (_flags.setContentMode)
|
||||
if (flags.setContentMode)
|
||||
view.contentMode = contentMode;
|
||||
|
||||
if (_flags.setUserInteractionEnabled)
|
||||
if (flags.setUserInteractionEnabled)
|
||||
view.userInteractionEnabled = userInteractionEnabled;
|
||||
|
||||
#if TARGET_OS_IOS
|
||||
if (_flags.setExclusiveTouch)
|
||||
if (flags.setExclusiveTouch)
|
||||
view.exclusiveTouch = exclusiveTouch;
|
||||
#endif
|
||||
|
||||
if (_flags.setShadowColor)
|
||||
if (flags.setShadowColor)
|
||||
layer.shadowColor = shadowColor;
|
||||
|
||||
if (_flags.setShadowOpacity)
|
||||
if (flags.setShadowOpacity)
|
||||
layer.shadowOpacity = shadowOpacity;
|
||||
|
||||
if (_flags.setShadowOffset)
|
||||
if (flags.setShadowOffset)
|
||||
layer.shadowOffset = shadowOffset;
|
||||
|
||||
if (_flags.setShadowRadius)
|
||||
if (flags.setShadowRadius)
|
||||
layer.shadowRadius = shadowRadius;
|
||||
|
||||
if (_flags.setBorderWidth)
|
||||
if (flags.setBorderWidth)
|
||||
layer.borderWidth = borderWidth;
|
||||
|
||||
if (_flags.setBorderColor)
|
||||
if (flags.setBorderColor)
|
||||
layer.borderColor = borderColor;
|
||||
|
||||
if (_flags.setAutoresizingMask)
|
||||
if (flags.setAutoresizingMask)
|
||||
view.autoresizingMask = autoresizingMask;
|
||||
|
||||
if (_flags.setAutoresizesSubviews)
|
||||
if (flags.setAutoresizesSubviews)
|
||||
view.autoresizesSubviews = autoresizesSubviews;
|
||||
|
||||
if (_flags.setNeedsDisplayOnBoundsChange)
|
||||
if (flags.setNeedsDisplayOnBoundsChange)
|
||||
layer.needsDisplayOnBoundsChange = needsDisplayOnBoundsChange;
|
||||
|
||||
if (_flags.setAllowsEdgeAntialiasing)
|
||||
if (flags.setAllowsEdgeAntialiasing)
|
||||
layer.allowsEdgeAntialiasing = allowsEdgeAntialiasing;
|
||||
|
||||
if (_flags.setEdgeAntialiasingMask)
|
||||
if (flags.setEdgeAntialiasingMask)
|
||||
layer.edgeAntialiasingMask = edgeAntialiasingMask;
|
||||
|
||||
if (_flags.needsDisplay)
|
||||
if (flags.needsDisplay)
|
||||
[view setNeedsDisplay];
|
||||
|
||||
if (_flags.needsLayout)
|
||||
if (flags.needsLayout)
|
||||
[view setNeedsLayout];
|
||||
|
||||
if (_flags.setAsyncTransactionContainer)
|
||||
if (flags.setAsyncTransactionContainer)
|
||||
view.asyncdisplaykit_asyncTransactionContainer = asyncTransactionContainer;
|
||||
|
||||
if (_flags.setOpaque)
|
||||
if (flags.setOpaque)
|
||||
ASDisplayNodeAssert(view.layer.opaque == opaque, @"Didn't set opaque as desired");
|
||||
|
||||
if (_flags.setIsAccessibilityElement)
|
||||
if (flags.setIsAccessibilityElement)
|
||||
view.isAccessibilityElement = isAccessibilityElement;
|
||||
|
||||
if (_flags.setAccessibilityLabel)
|
||||
if (flags.setAccessibilityLabel)
|
||||
view.accessibilityLabel = accessibilityLabel;
|
||||
|
||||
if (_flags.setAccessibilityHint)
|
||||
if (flags.setAccessibilityHint)
|
||||
view.accessibilityHint = accessibilityHint;
|
||||
|
||||
if (_flags.setAccessibilityValue)
|
||||
if (flags.setAccessibilityValue)
|
||||
view.accessibilityValue = accessibilityValue;
|
||||
|
||||
if (_flags.setAccessibilityTraits)
|
||||
if (flags.setAccessibilityTraits)
|
||||
view.accessibilityTraits = accessibilityTraits;
|
||||
|
||||
if (_flags.setAccessibilityFrame)
|
||||
if (flags.setAccessibilityFrame)
|
||||
view.accessibilityFrame = accessibilityFrame;
|
||||
|
||||
if (_flags.setAccessibilityLanguage)
|
||||
if (flags.setAccessibilityLanguage)
|
||||
view.accessibilityLanguage = accessibilityLanguage;
|
||||
|
||||
if (_flags.setAccessibilityElementsHidden)
|
||||
if (flags.setAccessibilityElementsHidden)
|
||||
view.accessibilityElementsHidden = accessibilityElementsHidden;
|
||||
|
||||
if (_flags.setAccessibilityViewIsModal)
|
||||
if (flags.setAccessibilityViewIsModal)
|
||||
view.accessibilityViewIsModal = accessibilityViewIsModal;
|
||||
|
||||
if (_flags.setShouldGroupAccessibilityChildren)
|
||||
if (flags.setShouldGroupAccessibilityChildren)
|
||||
view.shouldGroupAccessibilityChildren = shouldGroupAccessibilityChildren;
|
||||
|
||||
if (_flags.setAccessibilityIdentifier)
|
||||
if (flags.setAccessibilityIdentifier)
|
||||
view.accessibilityIdentifier = accessibilityIdentifier;
|
||||
}
|
||||
|
||||
@ -806,81 +804,31 @@ static UIColor *defaultTintColor = nil;
|
||||
if (!layer) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_ASPendingState *pendingState = [[_ASPendingState alloc] init];
|
||||
|
||||
pendingState.anchorPoint = layer.anchorPoint;
|
||||
(pendingState->_flags).setAnchorPoint = YES;
|
||||
|
||||
pendingState.position = layer.position;
|
||||
(pendingState->_flags).setPosition = YES;
|
||||
|
||||
pendingState.zPosition = layer.zPosition;
|
||||
(pendingState->_flags).setZPosition = YES;
|
||||
|
||||
pendingState.bounds = layer.bounds;
|
||||
(pendingState->_flags).setBounds = YES;
|
||||
|
||||
pendingState.contentsScale = layer.contentsScale;
|
||||
(pendingState->_flags).setContentsScale = YES;
|
||||
|
||||
pendingState.transform = layer.transform;
|
||||
(pendingState->_flags).setTransform = YES;
|
||||
|
||||
pendingState.sublayerTransform = layer.sublayerTransform;
|
||||
(pendingState->_flags).setSublayerTransform = YES;
|
||||
|
||||
pendingState.contents = layer.contents;
|
||||
(pendingState->_flags).setContents = YES;
|
||||
|
||||
pendingState.clipsToBounds = layer.masksToBounds;
|
||||
(pendingState->_flags).setClipsToBounds = YES;
|
||||
|
||||
pendingState.backgroundColor = layer.backgroundColor;
|
||||
(pendingState->_flags).setBackgroundColor = YES;
|
||||
|
||||
pendingState.opaque = layer.opaque;
|
||||
(pendingState->_flags).setOpaque = YES;
|
||||
|
||||
pendingState.hidden = layer.hidden;
|
||||
(pendingState->_flags).setHidden = YES;
|
||||
|
||||
pendingState.alpha = layer.opacity;
|
||||
(pendingState->_flags).setAlpha = YES;
|
||||
|
||||
pendingState.cornerRadius = layer.cornerRadius;
|
||||
(pendingState->_flags).setCornerRadius = YES;
|
||||
|
||||
pendingState.contentMode = ASDisplayNodeUIContentModeFromCAContentsGravity(layer.contentsGravity);
|
||||
(pendingState->_flags).setContentMode = YES;
|
||||
|
||||
pendingState.shadowColor = layer.shadowColor;
|
||||
(pendingState->_flags).setShadowColor = YES;
|
||||
|
||||
pendingState.shadowOpacity = layer.shadowOpacity;
|
||||
(pendingState->_flags).setShadowOpacity = YES;
|
||||
|
||||
pendingState.shadowOffset = layer.shadowOffset;
|
||||
(pendingState->_flags).setShadowOffset = YES;
|
||||
|
||||
pendingState.shadowRadius = layer.shadowRadius;
|
||||
(pendingState->_flags).setShadowRadius = YES;
|
||||
|
||||
pendingState.borderWidth = layer.borderWidth;
|
||||
(pendingState->_flags).setBorderWidth = YES;
|
||||
|
||||
pendingState.borderColor = layer.borderColor;
|
||||
(pendingState->_flags).setBorderColor = YES;
|
||||
|
||||
pendingState.needsDisplayOnBoundsChange = layer.needsDisplayOnBoundsChange;
|
||||
(pendingState->_flags).setNeedsDisplayOnBoundsChange = YES;
|
||||
|
||||
pendingState.allowsEdgeAntialiasing = layer.allowsEdgeAntialiasing;
|
||||
(pendingState->_flags).setAllowsEdgeAntialiasing = YES;
|
||||
|
||||
pendingState.edgeAntialiasingMask = layer.edgeAntialiasingMask;
|
||||
(pendingState->_flags).setEdgeAntialiasingMask = YES;
|
||||
|
||||
return pendingState;
|
||||
}
|
||||
|
||||
@ -890,134 +838,110 @@ static UIColor *defaultTintColor = nil;
|
||||
if (!view) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_ASPendingState *pendingState = [[_ASPendingState alloc] init];
|
||||
|
||||
|
||||
CALayer *layer = view.layer;
|
||||
|
||||
pendingState.anchorPoint = layer.anchorPoint;
|
||||
(pendingState->_flags).setAnchorPoint = YES;
|
||||
|
||||
pendingState.position = layer.position;
|
||||
(pendingState->_flags).setPosition = YES;
|
||||
|
||||
pendingState.zPosition = layer.zPosition;
|
||||
(pendingState->_flags).setZPosition = YES;
|
||||
|
||||
pendingState.bounds = view.bounds;
|
||||
(pendingState->_flags).setBounds = YES;
|
||||
|
||||
pendingState.contentsScale = layer.contentsScale;
|
||||
(pendingState->_flags).setContentsScale = YES;
|
||||
|
||||
pendingState.transform = layer.transform;
|
||||
(pendingState->_flags).setTransform = YES;
|
||||
|
||||
pendingState.sublayerTransform = layer.sublayerTransform;
|
||||
(pendingState->_flags).setSublayerTransform = YES;
|
||||
|
||||
pendingState.contents = layer.contents;
|
||||
(pendingState->_flags).setContents = YES;
|
||||
|
||||
pendingState.clipsToBounds = view.clipsToBounds;
|
||||
(pendingState->_flags).setClipsToBounds = YES;
|
||||
|
||||
pendingState.backgroundColor = layer.backgroundColor;
|
||||
(pendingState->_flags).setBackgroundColor = YES;
|
||||
|
||||
pendingState.tintColor = view.tintColor;
|
||||
(pendingState->_flags).setTintColor = YES;
|
||||
|
||||
pendingState.opaque = layer.opaque;
|
||||
(pendingState->_flags).setOpaque = YES;
|
||||
|
||||
pendingState.hidden = view.hidden;
|
||||
(pendingState->_flags).setHidden = YES;
|
||||
|
||||
pendingState.alpha = view.alpha;
|
||||
(pendingState->_flags).setAlpha = YES;
|
||||
|
||||
pendingState.cornerRadius = layer.cornerRadius;
|
||||
(pendingState->_flags).setCornerRadius = YES;
|
||||
|
||||
pendingState.contentMode = view.contentMode;
|
||||
(pendingState->_flags).setContentMode = YES;
|
||||
|
||||
pendingState.userInteractionEnabled = view.userInteractionEnabled;
|
||||
(pendingState->_flags).setUserInteractionEnabled = YES;
|
||||
#if TARGET_OS_IOS
|
||||
pendingState.exclusiveTouch = view.exclusiveTouch;
|
||||
(pendingState->_flags).setExclusiveTouch = YES;
|
||||
#endif
|
||||
pendingState.shadowColor = layer.shadowColor;
|
||||
(pendingState->_flags).setShadowColor = YES;
|
||||
|
||||
pendingState.shadowOpacity = layer.shadowOpacity;
|
||||
(pendingState->_flags).setShadowOpacity = YES;
|
||||
|
||||
pendingState.shadowOffset = layer.shadowOffset;
|
||||
(pendingState->_flags).setShadowOffset = YES;
|
||||
|
||||
pendingState.shadowRadius = layer.shadowRadius;
|
||||
(pendingState->_flags).setShadowRadius = YES;
|
||||
|
||||
pendingState.borderWidth = layer.borderWidth;
|
||||
(pendingState->_flags).setBorderWidth = YES;
|
||||
|
||||
pendingState.borderColor = layer.borderColor;
|
||||
(pendingState->_flags).setBorderColor = YES;
|
||||
|
||||
pendingState.autoresizingMask = view.autoresizingMask;
|
||||
(pendingState->_flags).setAutoresizingMask = YES;
|
||||
|
||||
pendingState.autoresizesSubviews = view.autoresizesSubviews;
|
||||
(pendingState->_flags).setAutoresizesSubviews = YES;
|
||||
|
||||
pendingState.needsDisplayOnBoundsChange = layer.needsDisplayOnBoundsChange;
|
||||
(pendingState->_flags).setNeedsDisplayOnBoundsChange = YES;
|
||||
|
||||
pendingState.allowsEdgeAntialiasing = layer.allowsEdgeAntialiasing;
|
||||
(pendingState->_flags).setAllowsEdgeAntialiasing = YES;
|
||||
|
||||
pendingState.edgeAntialiasingMask = layer.edgeAntialiasingMask;
|
||||
(pendingState->_flags).setEdgeAntialiasingMask = YES;
|
||||
|
||||
pendingState.isAccessibilityElement = view.isAccessibilityElement;
|
||||
(pendingState->_flags).setIsAccessibilityElement = YES;
|
||||
|
||||
pendingState.accessibilityLabel = view.accessibilityLabel;
|
||||
(pendingState->_flags).setAccessibilityLabel = YES;
|
||||
|
||||
pendingState.accessibilityHint = view.accessibilityHint;
|
||||
(pendingState->_flags).setAccessibilityHint = YES;
|
||||
|
||||
pendingState.accessibilityValue = view.accessibilityValue;
|
||||
(pendingState->_flags).setAccessibilityValue = YES;
|
||||
|
||||
pendingState.accessibilityTraits = view.accessibilityTraits;
|
||||
(pendingState->_flags).setAccessibilityTraits = YES;
|
||||
|
||||
pendingState.accessibilityFrame = view.accessibilityFrame;
|
||||
(pendingState->_flags).setAccessibilityFrame = YES;
|
||||
|
||||
pendingState.accessibilityLanguage = view.accessibilityLanguage;
|
||||
(pendingState->_flags).setAccessibilityLanguage = YES;
|
||||
|
||||
pendingState.accessibilityElementsHidden = view.accessibilityElementsHidden;
|
||||
(pendingState->_flags).setAccessibilityElementsHidden = YES;
|
||||
|
||||
pendingState.accessibilityViewIsModal = view.accessibilityViewIsModal;
|
||||
(pendingState->_flags).setAccessibilityViewIsModal = YES;
|
||||
|
||||
pendingState.shouldGroupAccessibilityChildren = view.shouldGroupAccessibilityChildren;
|
||||
(pendingState->_flags).setShouldGroupAccessibilityChildren = YES;
|
||||
|
||||
pendingState.accessibilityIdentifier = view.accessibilityIdentifier;
|
||||
(pendingState->_flags).setAccessibilityIdentifier = YES;
|
||||
|
||||
return pendingState;
|
||||
}
|
||||
|
||||
- (void)clearChanges
|
||||
{
|
||||
_flags = (ASPendingStateFlags){ 0 };
|
||||
}
|
||||
|
||||
- (BOOL)hasChanges
|
||||
{
|
||||
ASPendingStateFlags flags = _flags;
|
||||
|
||||
return (flags.setAnchorPoint
|
||||
|| flags.setPosition
|
||||
|| flags.setZPosition
|
||||
|| flags.setFrame
|
||||
|| flags.setBounds
|
||||
|| flags.setPosition
|
||||
|| flags.setContentsScale
|
||||
|| flags.setTransform
|
||||
|| flags.setSublayerTransform
|
||||
|| flags.setContents
|
||||
|| flags.setClipsToBounds
|
||||
|| flags.setBackgroundColor
|
||||
|| flags.setTintColor
|
||||
|| flags.setHidden
|
||||
|| flags.setAlpha
|
||||
|| flags.setCornerRadius
|
||||
|| flags.setContentMode
|
||||
|| flags.setUserInteractionEnabled
|
||||
|| flags.setExclusiveTouch
|
||||
|| flags.setShadowOpacity
|
||||
|| flags.setShadowOffset
|
||||
|| flags.setShadowRadius
|
||||
|| flags.setShadowColor
|
||||
|| flags.setBorderWidth
|
||||
|| flags.setBorderColor
|
||||
|| flags.setAutoresizingMask
|
||||
|| flags.setAutoresizesSubviews
|
||||
|| flags.setNeedsDisplayOnBoundsChange
|
||||
|| flags.setAllowsEdgeAntialiasing
|
||||
|| flags.setEdgeAntialiasingMask
|
||||
|| flags.needsDisplay
|
||||
|| flags.needsLayout
|
||||
|| flags.setAsyncTransactionContainer
|
||||
|| flags.setOpaque
|
||||
|| flags.setIsAccessibilityElement
|
||||
|| flags.setAccessibilityLabel
|
||||
|| flags.setAccessibilityHint
|
||||
|| flags.setAccessibilityValue
|
||||
|| flags.setAccessibilityTraits
|
||||
|| flags.setAccessibilityFrame
|
||||
|| flags.setAccessibilityLanguage
|
||||
|| flags.setAccessibilityElementsHidden
|
||||
|| flags.setAccessibilityViewIsModal
|
||||
|| flags.setShouldGroupAccessibilityChildren
|
||||
|| flags.setAccessibilityIdentifier);
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
CGColorRelease(backgroundColor);
|
||||
|
||||
40
AsyncDisplayKitTests/ASPendingStateControllerTests.m
Normal file
40
AsyncDisplayKitTests/ASPendingStateControllerTests.m
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// ASPendingStateControllerTests.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 1/7/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "ASPendingStateController.h"
|
||||
#import "ASDisplayNode.h"
|
||||
|
||||
@interface ASPendingStateController (Testing)
|
||||
- (BOOL)test_isFlushScheduled;
|
||||
@end
|
||||
|
||||
@interface ASPendingStateControllerTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASPendingStateControllerTests
|
||||
|
||||
- (void)testTheresASharedInstance
|
||||
{
|
||||
XCTAssertNotNil([ASPendingStateController sharedInstance]);
|
||||
}
|
||||
|
||||
- (void)testThatRegisteringANodeCausesAtFlushAtRunLoopEnd
|
||||
{
|
||||
ASPendingStateController *ctrl = [ASPendingStateController sharedInstance];
|
||||
ASDisplayNode *node = [ASDisplayNode new];
|
||||
XCTAssertFalse(ctrl.test_isFlushScheduled);
|
||||
[ctrl registerNode:node];
|
||||
XCTAssertTrue(ctrl.test_isFlushScheduled);
|
||||
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:1];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout];
|
||||
XCTAssertFalse(ctrl.test_isFlushScheduled);
|
||||
}
|
||||
|
||||
@end
|
||||
134
AsyncDisplayKitTests/ASWeakSetTests.m
Normal file
134
AsyncDisplayKitTests/ASWeakSetTests.m
Normal file
@ -0,0 +1,134 @@
|
||||
//
|
||||
// ASWeakSetTests.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 1/7/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "ASWeakSet.h"
|
||||
|
||||
@interface ASWeakSetTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASWeakSetTests
|
||||
|
||||
- (void)testAddingACoupleRetainedObjects
|
||||
{
|
||||
ASWeakSet <NSString *> *weakSet = [ASWeakSet new];
|
||||
NSString *hello = @"hello";
|
||||
NSString *world = @"hello";
|
||||
[weakSet addObject:hello];
|
||||
[weakSet addObject:world];
|
||||
XCTAssert([weakSet containsObject:hello]);
|
||||
XCTAssert([weakSet containsObject:world]);
|
||||
XCTAssert(![weakSet containsObject:@"apple"]);
|
||||
}
|
||||
|
||||
- (void)testThatCountIncorporatesDeallocatedObjects
|
||||
{
|
||||
ASWeakSet *weakSet = [ASWeakSet new];
|
||||
XCTAssertEqual(weakSet.count, 0);
|
||||
NSObject *a = [NSObject new];
|
||||
NSObject *b = [NSObject new];
|
||||
[weakSet addObject:a];
|
||||
[weakSet addObject:b];
|
||||
XCTAssertEqual(weakSet.count, 2);
|
||||
|
||||
@autoreleasepool {
|
||||
NSObject *doomedObject = [NSObject new];
|
||||
[weakSet addObject:doomedObject];
|
||||
XCTAssertEqual(weakSet.count, 3);
|
||||
}
|
||||
|
||||
XCTAssertEqual(weakSet.count, 2);
|
||||
}
|
||||
|
||||
- (void)testThatIsEmptyIncorporatesDeallocatedObjects
|
||||
{
|
||||
ASWeakSet *weakSet = [ASWeakSet new];
|
||||
XCTAssertTrue(weakSet.isEmpty);
|
||||
@autoreleasepool {
|
||||
NSObject *doomedObject = [NSObject new];
|
||||
[weakSet addObject:doomedObject];
|
||||
XCTAssertFalse(weakSet.isEmpty);
|
||||
}
|
||||
XCTAssertTrue(weakSet.isEmpty);
|
||||
}
|
||||
|
||||
- (void)testThatContainsObjectWorks
|
||||
{
|
||||
ASWeakSet *weakSet = [ASWeakSet new];
|
||||
NSObject *a = [NSObject new];
|
||||
NSObject *b = [NSObject new];
|
||||
[weakSet addObject:a];
|
||||
XCTAssertTrue([weakSet containsObject:a]);
|
||||
XCTAssertFalse([weakSet containsObject:b]);
|
||||
}
|
||||
|
||||
- (void)testThatRemoveObjectWorks
|
||||
{
|
||||
ASWeakSet *weakSet = [ASWeakSet new];
|
||||
NSObject *a = [NSObject new];
|
||||
NSObject *b = [NSObject new];
|
||||
[weakSet addObject:a];
|
||||
[weakSet addObject:b];
|
||||
XCTAssertTrue([weakSet containsObject:a]);
|
||||
XCTAssertTrue([weakSet containsObject:b]);
|
||||
XCTAssertEqual(weakSet.count, 2);
|
||||
|
||||
[weakSet removeObject:b];
|
||||
XCTAssertTrue([weakSet containsObject:a]);
|
||||
XCTAssertFalse([weakSet containsObject:b]);
|
||||
XCTAssertEqual(weakSet.count, 1);
|
||||
}
|
||||
|
||||
- (void)testThatFastEnumerationWorks
|
||||
{
|
||||
ASWeakSet *weakSet = [ASWeakSet new];
|
||||
NSObject *a = [NSObject new];
|
||||
NSObject *b = [NSObject new];
|
||||
[weakSet addObject:a];
|
||||
[weakSet addObject:b];
|
||||
|
||||
@autoreleasepool {
|
||||
NSObject *doomedObject = [NSObject new];
|
||||
[weakSet addObject:doomedObject];
|
||||
XCTAssertEqual(weakSet.count, 3);
|
||||
}
|
||||
|
||||
NSInteger i = 0;
|
||||
NSMutableSet *awaitingObjects = [NSMutableSet setWithObjects:a, b, nil];
|
||||
for (NSObject *object in weakSet) {
|
||||
XCTAssertTrue([awaitingObjects containsObject:object]);
|
||||
[awaitingObjects removeObject:object];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
XCTAssertEqual(i, 2);
|
||||
}
|
||||
|
||||
- (void)testThatRemoveAllObjectsWorks
|
||||
{
|
||||
ASWeakSet *weakSet = [ASWeakSet new];
|
||||
NSObject *a = [NSObject new];
|
||||
NSObject *b = [NSObject new];
|
||||
[weakSet addObject:a];
|
||||
[weakSet addObject:b];
|
||||
XCTAssertEqual(weakSet.count, 2);
|
||||
|
||||
[weakSet removeAllObjects];
|
||||
|
||||
XCTAssertEqual(weakSet.count, 0);
|
||||
|
||||
NSInteger i = 0;
|
||||
for (__unused NSObject *object in weakSet) {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
XCTAssertEqual(i, 0);
|
||||
}
|
||||
|
||||
@end
|
||||
Loading…
x
Reference in New Issue
Block a user