Create a centralized configuration API (#747)

* Update the dangerfile

* Make a trivial change to test new dangerfile

* Try out the new value with another trivial change

* Add a configuration API to make a unified place for pulling config from clients safely

* Specify properties for delegate

* Finish removing text experiment global enable

* Generate the config file

* Clean up configuration to fix tests

* Work on making it serializable

* Finish it up

* Fix example code

* Update sample project

* Clean up a few things

* Align with new project order

* Make it faster and update license header

* Add an option to specify your config at compile time

* Update another license header

* Add a version field, and bring interface state coalescing into configuration

* Update CA queue code

* Update CATransactionQueue tests

* Turn transaction queue on by default (for now, see comment)

* Update the tests

* Update the tests AGAIN

* Remove unused ordered set
This commit is contained in:
Adlai Holler
2018-03-25 12:52:57 -07:00
committed by GitHub
parent 3d9fe8c3a7
commit 27fac9f586
46 changed files with 840 additions and 322 deletions

View File

@@ -327,6 +327,8 @@
CC0F886C1E4286FA00576FED /* ReferenceImages_64 in Resources */ = {isa = PBXBuildFile; fileRef = CC0F88691E4286FA00576FED /* ReferenceImages_64 */; };
CC0F886D1E4286FA00576FED /* ReferenceImages_iOS_10 in Resources */ = {isa = PBXBuildFile; fileRef = CC0F886A1E4286FA00576FED /* ReferenceImages_iOS_10 */; };
CC11F97A1DB181180024D77B /* ASNetworkImageNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC11F9791DB181180024D77B /* ASNetworkImageNodeTests.m */; };
CC18248C200D49C800875940 /* ASTextNodeCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = CC18248B200D49C800875940 /* ASTextNodeCommon.h */; settings = {ATTRIBUTES = (Public, ); }; };
CC224E962066CA6D00BBA57F /* configuration.json in Resources */ = {isa = PBXBuildFile; fileRef = CC224E952066CA6D00BBA57F /* configuration.json */; };
CC2F65EE1E5FFB1600DA57C9 /* ASMutableElementMap.h in Headers */ = {isa = PBXBuildFile; fileRef = CC2F65EC1E5FFB1600DA57C9 /* ASMutableElementMap.h */; };
CC2F65EF1E5FFB1600DA57C9 /* ASMutableElementMap.m in Sources */ = {isa = PBXBuildFile; fileRef = CC2F65ED1E5FFB1600DA57C9 /* ASMutableElementMap.m */; };
CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -355,6 +357,8 @@
CC58AA4B1E398E1D002C8CB4 /* ASBlockTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC58AA4A1E398E1D002C8CB4 /* ASBlockTypes.h */; settings = {ATTRIBUTES = (Public, ); }; };
CC6AA2DA1E9F03B900978E87 /* ASDisplayNode+Ancestry.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6AA2D81E9F03B900978E87 /* ASDisplayNode+Ancestry.h */; settings = {ATTRIBUTES = (Public, ); }; };
CC6AA2DB1E9F03B900978E87 /* ASDisplayNode+Ancestry.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6AA2D91E9F03B900978E87 /* ASDisplayNode+Ancestry.m */; };
CC7AF196200D9BD500A21BDE /* ASExperimentalFeatures.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7AF195200D9BD500A21BDE /* ASExperimentalFeatures.h */; settings = {ATTRIBUTES = (Public, ); }; };
CC7AF198200DAB2200A21BDE /* ASExperimentalFeatures.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7AF197200D9E8400A21BDE /* ASExperimentalFeatures.m */; };
CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */; };
CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
CC84C7F220474C5300A3851B /* ASCGImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = CC84C7F020474C5300A3851B /* ASCGImageBuffer.h */; };
@@ -413,6 +417,12 @@
CCED5E3E2020D36800395C40 /* ASNetworkImageLoadInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = CCED5E3C2020D36800395C40 /* ASNetworkImageLoadInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
CCED5E3F2020D36800395C40 /* ASNetworkImageLoadInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = CCED5E3D2020D36800395C40 /* ASNetworkImageLoadInfo.m */; };
CCED5E412020D49D00395C40 /* ASNetworkImageLoadInfo+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CCED5E402020D41600395C40 /* ASNetworkImageLoadInfo+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
CCEDDDCA200C2AC300FFCD0A /* ASConfigurationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = CCEDDDC8200C2AC300FFCD0A /* ASConfigurationInternal.h */; };
CCEDDDCB200C2AC300FFCD0A /* ASConfigurationInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDC9200C2AC300FFCD0A /* ASConfigurationInternal.m */; };
CCEDDDCD200C2CB900FFCD0A /* ASConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = CCEDDDCC200C2CB900FFCD0A /* ASConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
CCEDDDCF200C42A200FFCD0A /* ASConfigurationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = CCEDDDCE200C42A200FFCD0A /* ASConfigurationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
CCEDDDD1200C488000FFCD0A /* ASConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDD0200C488000FFCD0A /* ASConfiguration.m */; };
CCEDDDD9200C518800FFCD0A /* ASConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.m */; };
CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; };
@@ -816,6 +826,8 @@
CC0F88691E4286FA00576FED /* ReferenceImages_64 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ReferenceImages_64; sourceTree = "<group>"; };
CC0F886A1E4286FA00576FED /* ReferenceImages_iOS_10 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ReferenceImages_iOS_10; sourceTree = "<group>"; };
CC11F9791DB181180024D77B /* ASNetworkImageNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASNetworkImageNodeTests.m; sourceTree = "<group>"; };
CC18248B200D49C800875940 /* ASTextNodeCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASTextNodeCommon.h; sourceTree = "<group>"; };
CC224E952066CA6D00BBA57F /* configuration.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = configuration.json; sourceTree = "<group>"; };
CC2E317F1DAC353700EEE891 /* ASCollectionView+Undeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionView+Undeprecated.h"; sourceTree = "<group>"; };
CC2F65EC1E5FFB1600DA57C9 /* ASMutableElementMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMutableElementMap.h; sourceTree = "<group>"; };
CC2F65ED1E5FFB1600DA57C9 /* ASMutableElementMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASMutableElementMap.m; sourceTree = "<group>"; };
@@ -851,6 +863,8 @@
CC58AA4A1E398E1D002C8CB4 /* ASBlockTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASBlockTypes.h; sourceTree = "<group>"; };
CC6AA2D81E9F03B900978E87 /* ASDisplayNode+Ancestry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ASDisplayNode+Ancestry.h"; path = "Base/ASDisplayNode+Ancestry.h"; sourceTree = "<group>"; };
CC6AA2D91E9F03B900978E87 /* ASDisplayNode+Ancestry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ASDisplayNode+Ancestry.m"; path = "Base/ASDisplayNode+Ancestry.m"; sourceTree = "<group>"; };
CC7AF195200D9BD500A21BDE /* ASExperimentalFeatures.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASExperimentalFeatures.h; sourceTree = "<group>"; };
CC7AF197200D9E8400A21BDE /* ASExperimentalFeatures.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASExperimentalFeatures.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>"; };
@@ -919,6 +933,12 @@
CCED5E3C2020D36800395C40 /* ASNetworkImageLoadInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASNetworkImageLoadInfo.h; sourceTree = "<group>"; };
CCED5E3D2020D36800395C40 /* ASNetworkImageLoadInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASNetworkImageLoadInfo.m; sourceTree = "<group>"; };
CCED5E402020D41600395C40 /* ASNetworkImageLoadInfo+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ASNetworkImageLoadInfo+Private.h"; sourceTree = "<group>"; };
CCEDDDC8200C2AC300FFCD0A /* ASConfigurationInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASConfigurationInternal.h; sourceTree = "<group>"; };
CCEDDDC9200C2AC300FFCD0A /* ASConfigurationInternal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASConfigurationInternal.m; sourceTree = "<group>"; };
CCEDDDCC200C2CB900FFCD0A /* ASConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASConfiguration.h; sourceTree = "<group>"; };
CCEDDDCE200C42A200FFCD0A /* ASConfigurationDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASConfigurationDelegate.h; sourceTree = "<group>"; };
CCEDDDD0200C488000FFCD0A /* ASConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASConfiguration.m; sourceTree = "<group>"; };
CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASConfigurationTests.m; sourceTree = "<group>"; };
D3779BCFF841AD3EB56537ED /* Pods-AsyncDisplayKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.release.xcconfig"; sourceTree = "<group>"; };
D785F6601A74327E00291744 /* ASScrollNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASScrollNode.h; sourceTree = "<group>"; };
D785F6611A74327E00291744 /* ASScrollNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASScrollNode.mm; sourceTree = "<group>"; };
@@ -1043,6 +1063,7 @@
isa = PBXGroup;
children = (
058D09B1195D04C000B7D73C /* Source */,
CC224E942066CA6D00BBA57F /* Schemas */,
058D09C5195D04C000B7D73C /* Tests */,
058D09AE195D04C000B7D73C /* Frameworks */,
058D09AD195D04C000B7D73C /* Products */,
@@ -1092,6 +1113,9 @@
CC58AA4A1E398E1D002C8CB4 /* ASBlockTypes.h */,
DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */,
DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */,
CCEDDDCC200C2CB900FFCD0A /* ASConfiguration.h */,
CCEDDDD0200C488000FFCD0A /* ASConfiguration.m */,
CCEDDDCE200C42A200FFCD0A /* ASConfigurationDelegate.h */,
055F1A3A19ABD43F004DAFF1 /* ASCellNode.h */,
AC6456071B0A335000CF11B8 /* ASCellNode.mm */,
CC84C7F020474C5300A3851B /* ASCGImageBuffer.h */,
@@ -1123,6 +1147,8 @@
058D09DC195D050800B7D73C /* ASDisplayNodeExtras.mm */,
0587F9BB1A7309ED00AFF0BA /* ASEditableTextNode.h */,
0587F9BC1A7309ED00AFF0BA /* ASEditableTextNode.mm */,
CC7AF195200D9BD500A21BDE /* ASExperimentalFeatures.h */,
CC7AF197200D9E8400A21BDE /* ASExperimentalFeatures.m */,
058D09DD195D050800B7D73C /* ASImageNode.h */,
058D09DE195D050800B7D73C /* ASImageNode.mm */,
68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */,
@@ -1158,6 +1184,7 @@
055F1A3319ABD3E3004DAFF1 /* ASTableView.mm */,
AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */,
0574D5E119C110610097DC25 /* ASTableViewProtocols.h */,
CC18248B200D49C800875940 /* ASTextNodeCommon.h */,
058D09DF195D050800B7D73C /* ASTextNode.h */,
058D09E0195D050800B7D73C /* ASTextNode.mm */,
A373200E1C571B050011FC94 /* ASTextNode+Beta.h */,
@@ -1204,6 +1231,7 @@
CCDD148A1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.m */,
2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */,
9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.mm */,
CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.m */,
2911485B1A77147A005D0878 /* ASControlNodeTests.m */,
1A6C000F1FAB4ED400D05926 /* ASCornerLayoutSpecSnapshotTests.mm */,
ACF6ED541B178DC700DA7C62 /* ASDimensionTests.mm */,
@@ -1386,6 +1414,8 @@
058D0A01195D050800B7D73C /* Private */ = {
isa = PBXGroup;
children = (
CCEDDDC8200C2AC300FFCD0A /* ASConfigurationInternal.h */,
CCEDDDC9200C2AC300FFCD0A /* ASConfigurationInternal.m */,
CCE04B2A1E313EDA006AEBBB /* Collection Data Adapter */,
E52F8AEE1EAE659600B5A912 /* Collection Layout */,
6947B0BB1E36B4E30007C478 /* Layout */,
@@ -1602,6 +1632,14 @@
path = Layout;
sourceTree = "<group>";
};
CC224E942066CA6D00BBA57F /* Schemas */ = {
isa = PBXGroup;
children = (
CC224E952066CA6D00BBA57F /* configuration.json */,
);
path = Schemas;
sourceTree = "<group>";
};
CC583ABF1EF9BAB400134156 /* Common */ = {
isa = PBXGroup;
children = (
@@ -1777,6 +1815,7 @@
696F01EC1DD2AF450049FBD5 /* ASEventLog.h in Headers */,
690C35641E055C7B00069B91 /* ASDimensionInternal.h in Headers */,
3917EBD41E9C2FC400D04A01 /* _ASCollectionReusableView.h in Headers */,
CC18248C200D49C800875940 /* ASTextNodeCommon.h in Headers */,
698371DB1E4379CD00437585 /* ASNodeController+Beta.h in Headers */,
6907C2581DC4ECFE00374C66 /* ASObjectDescriptionHelpers.h in Headers */,
69E0E8A71D356C9400627613 /* ASEqualityHelpers.h in Headers */,
@@ -1829,6 +1868,7 @@
CC6AA2DA1E9F03B900978E87 /* ASDisplayNode+Ancestry.h in Headers */,
8021EC1D1D2B00B100799119 /* UIImage+ASConvenience.h in Headers */,
B35061FD1B010EFD0018CF92 /* ASDisplayNode+Subclasses.h in Headers */,
CCEDDDCD200C2CB900FFCD0A /* ASConfiguration.h in Headers */,
B35061FB1B010EFD0018CF92 /* ASDisplayNode.h in Headers */,
B35061FE1B010EFD0018CF92 /* ASDisplayNodeExtras.h in Headers */,
CC0F88601E4280B800576FED /* _ASCollectionViewCell.h in Headers */,
@@ -1841,6 +1881,7 @@
B35062021B010EFD0018CF92 /* ASImageNode.h in Headers */,
B350621F1B010EFD0018CF92 /* ASImageProtocols.h in Headers */,
34EFC75F1B701C8600AD841F /* ASInsetLayoutSpec.h in Headers */,
CCEDDDCA200C2AC300FFCD0A /* ASConfigurationInternal.h in Headers */,
34EFC7671B701CD900AD841F /* ASLayout.h in Headers */,
DBDB83951C6E879900D0098C /* ASPagerFlowLayout.h in Headers */,
34EFC7691B701CE100AD841F /* ASLayoutElement.h in Headers */,
@@ -1942,6 +1983,7 @@
34EFC76E1B701CF400AD841F /* ASRatioLayoutSpec.h in Headers */,
DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */,
CCA282C41E9EAE630037E8B7 /* ASLayerBackingTipProvider.h in Headers */,
CCEDDDCF200C42A200FFCD0A /* ASConfigurationDelegate.h in Headers */,
E5C347B31ECB40AA00EC4BE4 /* ASTableNode+Beta.h in Headers */,
6900C5F41E8072DA00BCD75C /* ASImageNode+Private.h in Headers */,
68B0277B1C1A79D60041016B /* ASDisplayNode+Beta.h in Headers */,
@@ -1953,6 +1995,7 @@
CCCCCCDB1EC3EF060087FE10 /* ASTextLine.h in Headers */,
9C70F20E1CDBE9E5007D6C76 /* NSArray+Diffing.h in Headers */,
CCCCCCE71EC3F0FC0087FE10 /* NSAttributedString+ASText.h in Headers */,
CC7AF196200D9BD500A21BDE /* ASExperimentalFeatures.h in Headers */,
CCCCCCDF1EC3EF060087FE10 /* ASTextRunDelegate.h in Headers */,
9C49C3701B853961000B0DD5 /* ASStackLayoutElement.h in Headers */,
34EFC7701B701CFA00AD841F /* ASStackLayoutDefines.h in Headers */,
@@ -2105,6 +2148,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CC224E962066CA6D00BBA57F /* configuration.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2175,6 +2219,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CCEDDDD9200C518800FFCD0A /* ASConfigurationTests.m in Sources */,
E51B78BF1F028ABF00E32604 /* ASLayoutFlatteningTests.m in Sources */,
4496D0731FA9EA6B001CC8D5 /* ASTraitCollectionTests.m in Sources */,
29CDC2E21AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.m in Sources */,
@@ -2315,6 +2360,7 @@
B35062181B010EFD0018CF92 /* ASDataController.mm in Sources */,
CCB1F95A1EFB60A5009C7475 /* ASLog.m in Sources */,
767E7F8E1C90191D0066C000 /* AsyncDisplayKit+Debug.m in Sources */,
CCEDDDCB200C2AC300FFCD0A /* ASConfigurationInternal.m in Sources */,
CCCCCCD61EC3EF060087FE10 /* ASTextDebugOption.m in Sources */,
34EFC75C1B701BD200AD841F /* ASDimension.mm in Sources */,
B350624E1B010EFD0018CF92 /* ASDisplayNode+AsyncDisplay.mm in Sources */,
@@ -2353,6 +2399,7 @@
DECBD6EA1BE56E1900CF4905 /* ASButtonNode.mm in Sources */,
CCCCCCE01EC3EF060087FE10 /* ASTextRunDelegate.m in Sources */,
CCCCCCDA1EC3EF060087FE10 /* ASTextLayout.m in Sources */,
CCEDDDD1200C488000FFCD0A /* ASConfiguration.m in Sources */,
254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.m in Sources */,
E5E2D7301EA780DF005C24C6 /* ASCollectionGalleryLayoutDelegate.mm in Sources */,
34EFC76B1B701CEB00AD841F /* ASLayoutSpec.mm in Sources */,
@@ -2383,6 +2430,7 @@
E54E81FD1EB357BD00FFE8E1 /* ASPageTable.m in Sources */,
34EFC7721B701D0300AD841F /* ASStackLayoutSpec.mm in Sources */,
7AB338661C55B3420055FDE8 /* ASRelativeLayoutSpec.mm in Sources */,
CC7AF198200DAB2200A21BDE /* ASExperimentalFeatures.m in Sources */,
E5B2252E1F17E521001E1431 /* ASDispatch.m in Sources */,
696F01EE1DD2AF450049FBD5 /* ASEventLog.mm in Sources */,
9C70F2051CDA4F06007D6C76 /* ASTraitCollection.m in Sources */,

View File

@@ -25,6 +25,7 @@
- [ASCollectionNode] Added support for interactive item movement. [Adlai Holler](https://github.com/Adlai-Holler)
- Added an experimental "no-copy" rendering API. See ASGraphicsContext.h for info. [Adlai Holler](https://github.com/Adlai-Holler)
- Dropped support for iOS 8. [Adlai Holler](https://github.com/Adlai-Holler)
- Added a configuration API a unified place to turn on/off experimental Texture features. See `ASConfiguration.h` for info. [Adlai Holler](https://github.com/Adlai-Holler)
- **Breaking** Changes to ASNetworkImageNode: [Adlai Holler](https://github.com/Adlai-Holler)
- Modified `ASImageDownloaderCompletion` to add an optional `id userInfo` field. Your custom downloader can pass `nil`.
- Modified the last argument to `-[ASNetworkImageNodeDelegate imageNode:didLoadImage:info:]` method from a struct to an object of new class `ASNetworkImageLoadInfo` which includes other metadata about the load operation.

View File

@@ -0,0 +1,23 @@
{
"id": "configuration.json",
"title": "configuration",
"description" : "Schema definition of a Texture Configuration",
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"version" : {
"type" : "number"
},
"experimental_features": {
"type": "array",
"items": {
"type": "string",
"enum": [
"exp_graphics_contexts",
"exp_text_node",
"exp_interface_state_coalesce"
]
}
}
}
}

62
Source/ASConfiguration.h Normal file
View File

@@ -0,0 +1,62 @@
//
// ASConfiguration.h
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASBaseDefines.h>
#import <AsyncDisplayKit/ASExperimentalFeatures.h>
@protocol ASConfigurationDelegate;
NS_ASSUME_NONNULL_BEGIN
static NSInteger const ASConfigurationSchemaCurrentVersion = 1;
AS_SUBCLASSING_RESTRICTED
@interface ASConfiguration : NSObject <NSCopying>
/**
* Initialize this configuration with the provided dictionary,
* or nil to create an empty configuration.
*
* The schema is located in `schemas/configuration.json`.
*/
- (instancetype)initWithDictionary:(nullable NSDictionary *)dictionary;
/**
* The delegate for configuration-related events.
* Delegate methods are called from a serial queue.
*/
@property (nonatomic, strong, nullable) id<ASConfigurationDelegate> delegate;
/**
* The experimental features to enable in Texture.
* See ASExperimentalFeatures for functions to convert to/from a string array.
*/
@property (nonatomic) ASExperimentalFeatures experimentalFeatures;
@end
/**
* Implement this method in a category to make your
* configuration available to Texture. It will be read
* only once and copied.
*
* NOTE: To specify your configuration at compile-time, you can
* define AS_FIXED_CONFIG_JSON as a C-string of JSON. This method
* will then be implemented to parse that string and generate
* a configuration.
*/
@interface ASConfiguration (UserProvided)
+ (ASConfiguration *)textureConfiguration NS_RETURNS_RETAINED;
@end
NS_ASSUME_NONNULL_END

67
Source/ASConfiguration.m Normal file
View File

@@ -0,0 +1,67 @@
//
// ASConfiguration.m
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <AsyncDisplayKit/ASConfiguration.h>
#import <AsyncDisplayKit/ASConfigurationInternal.h>
/// Not too performance-sensitive here.
/// Get this from C++, without the extra exception handling.
#define autotype __auto_type
@implementation ASConfiguration
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
if (self = [super init]) {
autotype featureStrings = ASDynamicCast(dictionary[@"experimental_features"], NSArray);
autotype version = ASDynamicCast(dictionary[@"version"], NSNumber).integerValue;
if (version != ASConfigurationSchemaCurrentVersion) {
NSLog(@"Texture warning: configuration schema is old version (%zd vs %zd)", version, ASConfigurationSchemaCurrentVersion);
}
self.experimentalFeatures = ASExperimentalFeaturesFromArray(featureStrings);
}
return self;
}
- (id)copyWithZone:(NSZone *)zone
{
ASConfiguration *config = [[ASConfiguration alloc] initWithDictionary:nil];
config.experimentalFeatures = self.experimentalFeatures;
config.delegate = self.delegate;
return config;
}
@end
//#define AS_FIXED_CONFIG_JSON "{ \"version\" : 1, \"experimental_features\": [ \"exp_text_node\" ] }"
#ifdef AS_FIXED_CONFIG_JSON
@implementation ASConfiguration (UserProvided)
+ (ASConfiguration *)textureConfiguration NS_RETURNS_RETAINED
{
NSData *data = [@AS_FIXED_CONFIG_JSON dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary *d = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (!d) {
NSAssert(NO, @"Error parsing fixed config string '%s': %@", AS_FIXED_CONFIG_JSON, error);
return nil;
} else {
return [[ASConfiguration alloc] initWithDictionary:d];
}
}
@end
#endif // AS_FIXED_CONFIG_JSON

View File

@@ -0,0 +1,31 @@
//
// ASConfigurationDelegate.h
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASConfiguration.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Used to communicate configuration-related events to the client.
*/
@protocol ASConfigurationDelegate <NSObject>
/**
* Texture performed its first behavior related to the feature(s).
* This can be useful for tracking the impact of the behavior (A/B testing).
*/
- (void)textureDidActivateExperimentalFeatures:(ASExperimentalFeatures)features;
@end
NS_ASSUME_NONNULL_END

View File

@@ -2915,7 +2915,7 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
}
};
if ([[ASCATransactionQueue sharedQueue] disabled]) {
if (!ASCATransactionQueue.sharedQueue.enabled) {
dispatch_async(dispatch_get_main_queue(), exitVisibleInterfaceState);
} else {
exitVisibleInterfaceState();
@@ -2980,7 +2980,7 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
- (void)setInterfaceState:(ASInterfaceState)newState
{
if ([[ASCATransactionQueue sharedQueue] disabled]) {
if (!ASCATransactionQueue.sharedQueue.enabled) {
[self applyPendingInterfaceState:newState];
} else {
ASDN::MutexLocker l(__instanceLock__);
@@ -3012,7 +3012,7 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
ASDN::MutexLocker l(__instanceLock__);
// newPendingState will not be used when ASCATransactionQueue is enabled
// and use _pendingInterfaceState instead for interfaceState update.
if ([[ASCATransactionQueue sharedQueue] disabled]) {
if (!ASCATransactionQueue.sharedQueue.enabled) {
_pendingInterfaceState = newPendingState;
}
oldState = _interfaceState;

View File

@@ -0,0 +1,36 @@
//
// ASExperimentalFeatures.h
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASBaseDefines.h>
NS_ASSUME_NONNULL_BEGIN
ASDISPLAYNODE_EXTERN_C_BEGIN
/**
* A bit mask of features.
*/
typedef NS_OPTIONS(NSUInteger, ASExperimentalFeatures) {
ASExperimentalGraphicsContexts = 1 << 0, // exp_graphics_contexts
ASExperimentalTextNode = 1 << 1, // exp_text_node
ASExperimentalInterfaceStateCoalescing = 1 << 2, // exp_interface_state_coalesce
ASExperimentalFeatureAll = 0xFFFFFFFF
};
/// Convert flags -> name array.
NSArray<NSString *> *ASExperimentalFeaturesGetNames(ASExperimentalFeatures flags);
/// Convert name array -> flags.
ASExperimentalFeatures ASExperimentalFeaturesFromArray(NSArray<NSString *> *array);
ASDISPLAYNODE_EXTERN_C_END
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,45 @@
//
// ASExperimentalFeatures.m
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <AsyncDisplayKit/ASExperimentalFeatures.h>
NSArray<NSString *> *ASExperimentalFeaturesGetNames(ASExperimentalFeatures flags)
{
NSArray *allNames = ASCreateOnce((@[@"exp_graphics_contexts",
@"exp_text_node",
@"exp_interface_state_coalesce"]));
if (flags == ASExperimentalFeatureAll) {
return allNames;
}
// Go through all names, testing each bit.
NSUInteger i = 0;
return ASArrayByFlatMapping(allNames, NSString *name, ({
(flags & (1 << i++)) ? name : nil;
}));
}
// O(N^2) but with counts this small, it's probably faster
// than hashing the strings.
ASExperimentalFeatures ASExperimentalFeaturesFromArray(NSArray<NSString *> *array)
{
NSArray *allNames = ASExperimentalFeaturesGetNames(ASExperimentalFeatureAll);
ASExperimentalFeatures result = 0;
for (NSString *str in array) {
NSUInteger i = [allNames indexOfObject:str];
if (i != NSNotFound) {
result |= (1 << i);
}
}
return result;
}

View File

@@ -1,9 +1,13 @@
//
// ASNetworkImageLoadInfo.h
// AsyncDisplayKit
// Texture
//
// Created by Adlai on 1/30/18.
// Copyright © 2018 Facebook. All rights reserved.
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <Foundation/Foundation.h>

View File

@@ -1,9 +1,13 @@
//
// ASNetworkImageLoadInfo.m
// AsyncDisplayKit
// Texture
//
// Created by Adlai on 1/30/18.
// Copyright © 2018 Facebook. All rights reserved.
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <AsyncDisplayKit/ASNetworkImageLoadInfo.h>

View File

@@ -59,7 +59,9 @@ AS_SUBCLASSING_RESTRICTED
@interface ASCATransactionQueue : ASAbstractRunLoopQueue
@property (atomic, readonly) BOOL isEmpty;
@property (atomic, readonly) BOOL disabled;
@property (atomic, readonly, getter=isEnabled) BOOL enabled;
/**
* The queue to run on main run loop before CATransaction commit.
*
@@ -72,11 +74,6 @@ AS_SUBCLASSING_RESTRICTED
- (void)enqueue:(id<ASCATransactionQueueObserving>)object;
/**
* @abstract Apply a node's interfaceState immediately rather than adding to the queue.
*/
- (void)disable;
@end

View File

@@ -16,6 +16,7 @@
//
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASConfigurationInternal.h>
#import <AsyncDisplayKit/ASLog.h>
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
#import <AsyncDisplayKit/ASRunLoopQueue.h>
@@ -494,7 +495,6 @@ typedef enum {
CFRunLoopObserverRef _postTransactionObserver;
NSPointerArray *_internalQueue;
ASDN::RecursiveMutex _internalQueueLock;
BOOL _disableInterfaceStateCoalesce;
BOOL _CATransactionCommitInProgress;
// In order to not pollute the top-level activities, each queue has 1 root activity.
@@ -671,7 +671,7 @@ static int const kASASCATransactionQueuePostOrder = 3000000;
return;
}
if (_disableInterfaceStateCoalesce || _CATransactionCommitInProgress) {
if (!self.enabled || _CATransactionCommitInProgress) {
[object prepareForCATransactionCommit];
return;
}
@@ -702,14 +702,9 @@ static int const kASASCATransactionQueuePostOrder = 3000000;
return _internalQueue.count == 0;
}
- (void)disable
- (BOOL)isEnabled
{
_disableInterfaceStateCoalesce = YES;
}
- (BOOL)disabled
{
return _disableInterfaceStateCoalesce;
return ASActivateExperimentalFeature(ASExperimentalInterfaceStateCoalescing);
}
@end

View File

@@ -21,20 +21,6 @@
NS_ASSUME_NONNULL_BEGIN
// When enabled, use ASTextNode2 for subclasses, random instances, or all instances of ASTextNode.
// See ASAvailability.h declaration of ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE for a compile-time option.
typedef NS_OPTIONS(NSUInteger, ASTextNodeExperimentOptions) {
// All subclass instances use the experimental implementation.
ASTextNodeExperimentSubclasses = 1 << 0,
// Random instances of ASTextNode (50% chance) (not subclasses) use experimental impl.
// Useful for profiling with apps that have no custom text node subclasses.
ASTextNodeExperimentRandomInstances = 1 << 1,
// All instances of ASTextNode itself use experimental implementation. Supersedes `.randomInstances`.
ASTextNodeExperimentAllInstances = 1 << 2,
// Add highlighting etc. for debugging.
ASTextNodeExperimentDebugging = 1 << 3
};
@interface ASTextNode ()
/**
@@ -52,14 +38,6 @@ typedef NS_OPTIONS(NSUInteger, ASTextNodeExperimentOptions) {
*/
@property (nonatomic, assign) UIEdgeInsets textContainerInset;
/**
* Opt in to an experimental implementation of text node. The implementation may improve performance and correctness,
* but may not support all features and has not been thoroughly tested in production.
*
* @precondition You may not call this after allocating any text nodes. You may only call this once.
*/
+ (void)setExperimentOptions:(ASTextNodeExperimentOptions)options;
/**
* Returns YES if this node is using the experimental implementation. NO otherwise. Will not change.
*/

View File

@@ -17,31 +17,10 @@
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASControlNode.h>
#if ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE
#import <AsyncDisplayKit/ASTextNode2.h>
#endif
#import <AsyncDisplayKit/ASTextNodeCommon.h>
NS_ASSUME_NONNULL_BEGIN
@protocol ASTextNodeDelegate;
#if !ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE
/**
* Highlight styles.
*/
typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
/**
* Highlight style for text on a light background.
*/
ASTextNodeHighlightStyleLight,
/**
* Highlight style for text on a dark background.
*/
ASTextNodeHighlightStyleDark
};
/**
@abstract Draws interactive rich text.
@discussion Backed by TextKit.
@@ -238,70 +217,6 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
@end
#else
@interface ASTextNode : ASTextNode2
@end
#endif
/**
* @abstract Text node delegate.
*/
@protocol ASTextNodeDelegate <NSObject>
@optional
/**
@abstract Indicates to the delegate that a link was tapped within a text node.
@param textNode The ASTextNode containing the link that was tapped.
@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 tapped.
@param textRange The range of highlighted text.
*/
- (void)textNode:(ASTextNode *)textNode tappedLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point textRange:(NSRange)textRange;
/**
@abstract Indicates to the delegate that a link was tapped within a text node.
@param textNode The ASTextNode containing the link that was tapped.
@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 tapped.
@param textRange The range of highlighted text.
@discussion In addition to implementing this method, the delegate must be set on the text
node before it is loaded (the recognizer is created in -didLoad)
*/
- (void)textNode:(ASTextNode *)textNode longPressedLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point textRange:(NSRange)textRange;
//! @abstract Called when the text node's truncation string has been tapped.
- (void)textNodeTappedTruncationToken:(ASTextNode *)textNode;
/**
@abstract Indicates to the text node if an attribute should be considered a link.
@param textNode The text node containing the entity attribute.
@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 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;
/**
@abstract Indicates to the text node if an attribute is a valid long-press target
@param textNode The text node containing the entity attribute.
@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 long-pressed.
@discussion If not implemented, the default value is NO.
@return YES if the entity attribute should be treated as a long-press target, NO otherwise.
*/
- (BOOL)textNode:(ASTextNode *)textNode shouldLongPressLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point;
@end
#if !ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE
@interface ASTextNode (Unavailable)
- (instancetype)initWithLayerBlock:(ASDisplayNodeLayerBlock)viewBlock didLoadBlock:(nullable ASDisplayNodeDidLoadBlock)didLoadBlock __unavailable;
@@ -334,6 +249,4 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
@end
#endif
NS_ASSUME_NONNULL_END

View File

@@ -18,7 +18,6 @@
#import <AsyncDisplayKit/ASTextNode.h>
#import <AsyncDisplayKit/ASTextNode2.h>
#if !ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE
#import <AsyncDisplayKit/ASTextNode+Beta.h>
#import <mutex>
@@ -27,6 +26,7 @@
#import <AsyncDisplayKit/_ASDisplayLayer.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASConfigurationInternal.h>
#import <AsyncDisplayKit/ASHighlightOverlayLayer.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
#import <AsyncDisplayKit/ASGraphicsContext.h>
@@ -1309,69 +1309,35 @@ static NSAttributedString *DefaultTruncationAttributedString()
}
#endif
// Allocate _experimentLock on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136)
static ASDN::StaticMutex& _experimentLock = *new ASDN::StaticMutex;
static ASTextNodeExperimentOptions _experimentOptions;
static BOOL _hasAllocatedNode;
+ (void)setExperimentOptions:(ASTextNodeExperimentOptions)options
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
ASDN::StaticMutexLocker lock(_experimentLock);
// They must call this before allocating any text nodes.
ASDisplayNodeAssertFalse(_hasAllocatedNode);
_experimentOptions = options;
// Set superclass of all subclasses to ASTextNode2
if (options & ASTextNodeExperimentSubclasses) {
unsigned int classCount;
Class originalClass = [ASTextNode class];
Class newClass = [ASTextNode2 class];
Class *classes = objc_copyClassList(&classCount);
for (int i = 0; i < classCount; i++) {
Class c = classes[i];
if (class_getSuperclass(c) == originalClass) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
class_setSuperclass(c, newClass);
#pragma clang diagnostic pop
}
}
free(classes);
}
if (options & ASTextNodeExperimentDebugging) {
[ASTextNode2 enableDebugging];
}
});
}
+ (id)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
ASDN::StaticMutexLocker lock(_experimentLock);
_hasAllocatedNode = YES;
});
// All instances || (random instances && rand() != 0)
BOOL useExperiment = (_experimentOptions & ASTextNodeExperimentAllInstances)
|| ((_experimentOptions & ASTextNodeExperimentRandomInstances)
&& (arc4random_uniform(2) != 0));
if (useExperiment) {
return (ASTextNode *)[ASTextNode2 allocWithZone:zone];
} else {
// If they're not experimenting, just forward.
if (!ASActivateExperimentalFeature(ASExperimentalTextNode)) {
return [super allocWithZone:zone];
}
}
// We are plain ASTextNode. Just swap in an ASTextNode2 instead.
if (self == [ASTextNode class]) {
return (ASTextNode *)[ASTextNode2 allocWithZone:zone];
}
// We are descended from ASTextNode. We need to change the superclass for the
// ASTextNode subclass to ASTextNode2.
// Walk up the class hierarchy until we find ASTextNode.
Class s;
for (Class c = self; c != [ASTextNode class]; c = s) {
s = class_getSuperclass(c);
if (s == [ASTextNode class]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// Direct descendent. Update superclass of c and end.
class_setSuperclass(c, [ASTextNode2 class]);
#pragma clang diagnostic pop
break;
}
}
- (BOOL)usingExperiment
{
return NO;
return [super allocWithZone:zone];
}
@end
@@ -1399,10 +1365,3 @@ static BOOL _hasAllocatedNode;
}
@end
#else
@implementation ASTextNode
@end
#endif

View File

@@ -11,28 +11,7 @@
//
#import <AsyncDisplayKit/ASControlNode.h>
#if !ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE
// Import this to get ASTextNodeHighlightStyle
#import <AsyncDisplayKit/ASTextNode.h>
#else
@protocol ASTextNodeDelegate;
/**
* Highlight styles.
*/
typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
/**
* Highlight style for text on a light background.
*/
ASTextNodeHighlightStyleLight,
/**
* Highlight style for text on a dark background.
*/
ASTextNodeHighlightStyleDark
};
#endif
#import <AsyncDisplayKit/ASTextNodeCommon.h>
NS_ASSUME_NONNULL_BEGIN

86
Source/ASTextNodeCommon.h Normal file
View File

@@ -0,0 +1,86 @@
//
// ASTextNodeCommon.h
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <Foundation/Foundation.h>
@class ASTextNode;
/**
* Highlight styles.
*/
typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
/**
* Highlight style for text on a light background.
*/
ASTextNodeHighlightStyleLight,
/**
* Highlight style for text on a dark background.
*/
ASTextNodeHighlightStyleDark
};
/**
* @abstract Text node delegate.
*/
@protocol ASTextNodeDelegate <NSObject>
@optional
/**
@abstract Indicates to the delegate that a link was tapped within a text node.
@param textNode The ASTextNode containing the link that was tapped.
@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 tapped.
@param textRange The range of highlighted text.
*/
- (void)textNode:(ASTextNode *)textNode tappedLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point textRange:(NSRange)textRange;
/**
@abstract Indicates to the delegate that a link was tapped within a text node.
@param textNode The ASTextNode containing the link that was tapped.
@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 tapped.
@param textRange The range of highlighted text.
@discussion In addition to implementing this method, the delegate must be set on the text
node before it is loaded (the recognizer is created in -didLoad)
*/
- (void)textNode:(ASTextNode *)textNode longPressedLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point textRange:(NSRange)textRange;
//! @abstract Called when the text node's truncation string has been tapped.
- (void)textNodeTappedTruncationToken:(ASTextNode *)textNode;
/**
@abstract Indicates to the text node if an attribute should be considered a link.
@param textNode The text node containing the entity attribute.
@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 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;
/**
@abstract Indicates to the text node if an attribute is a valid long-press target
@param textNode The text node containing the entity attribute.
@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 long-pressed.
@discussion If not implemented, the default value is NO.
@return YES if the entity attribute should be treated as a long-press target, NO otherwise.
*/
- (BOOL)textNode:(ASTextNode *)textNode shouldLongPressLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point;
@end

View File

@@ -21,6 +21,8 @@
#import <AsyncDisplayKit/ASDisplayNode+Ancestry.h>
#import <AsyncDisplayKit/ASDisplayNode+Convenience.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
#import <AsyncDisplayKit/ASConfiguration.h>
#import <AsyncDisplayKit/ASConfigurationDelegate.h>
#import <AsyncDisplayKit/ASControlNode.h>
#import <AsyncDisplayKit/ASImageNode.h>

View File

@@ -56,11 +56,8 @@
#define YOGA __has_include(YOGA_HEADER_PATH)
#endif
// When enabled, use ASTextNode2 for ALL instances of ASTextNode.
// This includes what ASButtonNode uses internally, as well as all app references to ASTextNode.
// See ASTextNode+Beta.h declaration of ASTextNodeExperimentOptions for more details.
#ifndef ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE
#define ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE 0
#ifdef ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE
#error "ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE is unavailable. See ASConfiguration.h."
#endif
#define AS_PIN_REMOTE_IMAGE __has_include(<PINRemoteImage/PINRemoteImage.h>)

View File

@@ -31,6 +31,11 @@ NS_ASSUME_NONNULL_BEGIN
AS_SUBCLASSING_RESTRICTED
@interface ASElementMap : NSObject <NSCopying, NSFastEnumeration>
/**
* The total number of elements in this map.
*/
@property (readonly) NSUInteger count;
/**
* The number of sections (of items) in this map.
*/

View File

@@ -75,6 +75,11 @@
return self;
}
- (NSUInteger)count
{
return _elementToIndexPathMap.count;
}
- (NSArray<NSIndexPath *> *)itemIndexPaths
{
return ASIndexPathsForTwoDimensionalArray(_sectionsOfItems);

View File

@@ -31,15 +31,6 @@
NS_ASSUME_NONNULL_BEGIN
ASDISPLAYNODE_EXTERN_C_BEGIN
/**
* Call this to enable the experimental no-copy rendering.
*
* Returns YES if it was enabled, or NO + assert if it's too late because
* rendering has already started. In practice it's fine to call this
* during -didFinishLaunchingWithOptions:.
*/
extern BOOL ASEnableNoCopyRendering(void);
/**
* Creates a one-shot context.
*

View File

@@ -13,36 +13,12 @@
#import "ASGraphicsContext.h"
#import <AsyncDisplayKit/ASCGImageBuffer.h>
#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASConfigurationInternal.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <UIKit/UIGraphics.h>
#import <UIKit/UIImage.h>
#import <stdatomic.h>
#import <objc/runtime.h>
#pragma mark - Feature Gating
// Two flags that we atomically manipulate to control the feature.
typedef NS_OPTIONS(uint, ASNoCopyFlags) {
ASNoCopyEnabled = 1 << 0,
ASNoCopyBlocked = 1 << 1
};
static atomic_uint __noCopyFlags;
// Check if it's blocked, and set the enabled flag if not.
extern BOOL ASEnableNoCopyRendering()
{
ASNoCopyFlags expectedFlags = 0;
BOOL enabled = atomic_compare_exchange_strong(&__noCopyFlags, &expectedFlags, ASNoCopyEnabled);
ASDisplayNodeCAssert(enabled, @"Can't enable no-copy rendering after first render started.");
return enabled;
}
// Check if it's enabled and set the "blocked" flag either way.
static BOOL ASNoCopyRenderingBlockAndCheckEnabled() {
ASNoCopyFlags oldFlags = atomic_fetch_or(&__noCopyFlags, ASNoCopyBlocked);
return (oldFlags & ASNoCopyEnabled) != 0;
}
/**
* Our version of the private CGBitmapGetAlignedBytesPerRow function.
*
@@ -67,7 +43,7 @@ static UInt8 __contextDataAssociationKey;
extern void ASGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)
{
if (!ASNoCopyRenderingBlockAndCheckEnabled()) {
if (!ASActivateExperimentalFeature(ASExperimentalGraphicsContexts)) {
UIGraphicsBeginImageContextWithOptions(size, opaque, scale);
return;
}
@@ -132,7 +108,7 @@ extern void ASGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGF
extern UIImage * _Nullable ASGraphicsGetImageAndEndCurrentContext() NS_RETURNS_RETAINED
{
if (!ASNoCopyRenderingBlockAndCheckEnabled()) {
if (!ASActivateExperimentalFeature(ASExperimentalGraphicsContexts)) {
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
@@ -186,7 +162,7 @@ extern UIImage * _Nullable ASGraphicsGetImageAndEndCurrentContext() NS_RETURNS_R
extern void ASGraphicsEndImageContext()
{
if (!ASNoCopyRenderingBlockAndCheckEnabled()) {
if (!ASActivateExperimentalFeature(ASExperimentalGraphicsContexts)) {
UIGraphicsEndImageContext();
return;
}

View File

@@ -0,0 +1,38 @@
//
// ASConfigurationInternal.h
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASConfiguration.h>
NS_ASSUME_NONNULL_BEGIN
ASDISPLAYNODE_EXTERN_C_BEGIN
/**
* Quickly check if an experiment is enabled and notify the delegate
* that it's been activated.
*
* The delegate will be notified asynchronously.
*/
BOOL ASActivateExperimentalFeature(ASExperimentalFeatures option);
AS_SUBCLASSING_RESTRICTED
@interface ASConfigurationManager : NSObject
/**
* No API for now.
* Just use ASActivateExperimentalFeature to access this efficiently.
*/
@end
NS_ASSUME_NONNULL_END
ASDISPLAYNODE_EXTERN_C_END

View File

@@ -0,0 +1,96 @@
//
// ASConfigurationInternal.m
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import "ASConfigurationInternal.h"
#import <AsyncDisplayKit/ASConfiguration.h>
#import <AsyncDisplayKit/ASConfigurationDelegate.h>
#import <stdatomic.h>
#define ASGetSharedConfigMgr() (__bridge ASConfigurationManager *)ASConfigurationManager.sharedInstance
@implementation ASConfigurationManager {
ASConfiguration *_config;
dispatch_queue_t _delegateQueue;
_Atomic(ASExperimentalFeatures) _activatedExperiments;
}
/// Return CFTypeRef to avoid retain/release on this singleton.
+ (CFTypeRef)sharedInstance
{
static CFTypeRef inst;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
inst = (__bridge_retained CFTypeRef)[[ASConfigurationManager alloc] init];
});
return inst;
}
+ (ASConfiguration *)defaultConfiguration NS_RETURNS_RETAINED
{
ASConfiguration *config = [[ASConfiguration alloc] init];
// On by default for now, pending fix for https://github.com/TextureGroup/Texture/issues/853
config.experimentalFeatures = ASExperimentalInterfaceStateCoalescing;
return config;
}
- (instancetype)init
{
if (self = [super init]) {
_delegateQueue = dispatch_queue_create("org.TextureGroup.Texture.ConfigNotifyQueue", DISPATCH_QUEUE_SERIAL);
if ([ASConfiguration respondsToSelector:@selector(textureConfiguration)]) {
_config = [[ASConfiguration textureConfiguration] copy];
} else {
_config = [ASConfigurationManager defaultConfiguration];
}
}
return self;
}
- (BOOL)activateExperimentalFeature:(ASExperimentalFeatures)requested
{
if (_config == nil) {
return NO;
}
NSAssert(__builtin_popcount(requested) == 1, @"Cannot activate multiple features at once with this method.");
// If they're disabled, ignore them.
ASExperimentalFeatures enabled = requested & _config.experimentalFeatures;
ASExperimentalFeatures prevTriggered = atomic_fetch_or(&_activatedExperiments, enabled);
ASExperimentalFeatures newlyTriggered = enabled & ~prevTriggered;
// Notify delegate if needed.
if (newlyTriggered != 0) {
__unsafe_unretained id<ASConfigurationDelegate> del = _config.delegate;
dispatch_async(_delegateQueue, ^{
[del textureDidActivateExperimentalFeatures:newlyTriggered];
});
}
return (enabled != 0);
}
#if DEBUG
+ (void)test_resetWithConfiguration:(ASConfiguration *)configuration
{
ASConfigurationManager *inst = ASGetSharedConfigMgr();
inst->_config = configuration ?: [self defaultConfiguration];
atomic_store(&inst->_activatedExperiments, 0);
}
#endif
@end
BOOL ASActivateExperimentalFeature(ASExperimentalFeatures feature)
{
return [ASGetSharedConfigMgr() activateExperimentalFeature:feature];
}

View File

@@ -1,9 +1,13 @@
//
// ASNetworkImageLoadInfo+Private.h
// AsyncDisplayKit
// Texture
//
// Created by Adlai on 1/30/18.
// Copyright © 2018 Facebook. All rights reserved.
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <AsyncDisplayKit/ASNetworkImageLoadInfo.h>

View File

@@ -862,7 +862,7 @@
[cn waitUntilAllUpdatesAreProcessed];
[cn.view layoutIfNeeded];
ASCellNode *node = [cn nodeForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
ASCATransactionQueueWait();
ASCATransactionQueueWait(nil);
XCTAssertTrue(node.visible);
testController.asyncDelegate->_itemCounts = {0};
[cn deleteItemsAtIndexPaths: @[[NSIndexPath indexPathForItem:0 inSection:0]]];
@@ -1074,7 +1074,7 @@
for (NSInteger i = 0; i < c; i++) {
NSIndexPath *ip = [NSIndexPath indexPathForItem:i inSection:s];
ASCellNode *node = [cn nodeForItemAtIndexPath:ip];
ASCATransactionQueueWait();
ASCATransactionQueueWait(nil);
if (node.inPreloadState) {
CGRect frame = [cn.view layoutAttributesForItemAtIndexPath:ip].frame;
r = CGRectUnion(r, frame);

View File

@@ -0,0 +1,77 @@
//
// ASConfigurationTests.m
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <XCTest/XCTest.h>
#import "ASTestCase.h"
#import "ASConfiguration.h"
#import "ASConfigurationDelegate.h"
#import "ASConfigurationInternal.h"
@interface ASConfigurationTests : ASTestCase <ASConfigurationDelegate>
@end
@implementation ASConfigurationTests {
void (^onActivate)(ASConfigurationTests *self, ASExperimentalFeatures feature);
}
- (void)testExperimentalFeatureConfig
{
// Set the config
ASConfiguration *config = [[ASConfiguration alloc] initWithDictionary:nil];
config.experimentalFeatures = ASExperimentalGraphicsContexts;
config.delegate = self;
[ASConfigurationManager test_resetWithConfiguration:config];
// Set an expectation for a callback, and assert we only get one.
XCTestExpectation *e = [self expectationWithDescription:@"Callback 1 done."];
onActivate = ^(ASConfigurationTests *self, ASExperimentalFeatures feature) {
XCTAssertEqual(feature, ASExperimentalGraphicsContexts);
[e fulfill];
// Next time it's a fail.
self->onActivate = ^(ASConfigurationTests *self, ASExperimentalFeatures feature) {
XCTFail(@"Too many callbacks.");
};
};
// Now activate the graphics experiment and expect it works.
XCTAssertTrue(ASActivateExperimentalFeature(ASExperimentalGraphicsContexts));
// We should get a callback here
// Now activate text node and expect it fails.
XCTAssertFalse(ASActivateExperimentalFeature(ASExperimentalTextNode));
[self waitForExpectationsWithTimeout:3 handler:nil];
}
- (void)textureDidActivateExperimentalFeatures:(ASExperimentalFeatures)feature
{
if (onActivate) {
onActivate(self, feature);
}
}
- (void)testMappingNamesToFlags
{
// Throw in a bad bit.
ASExperimentalFeatures features = ASExperimentalTextNode | ASExperimentalGraphicsContexts | (1 << 22);
NSArray *expectedNames = @[ @"exp_graphics_contexts", @"exp_text_node" ];
XCTAssertEqualObjects(expectedNames, ASExperimentalFeaturesGetNames(features));
}
- (void)testMappingFlagsFromNames
{
// Throw in a bad name.
NSArray *names = @[ @"exp_text_node", @"exp_graphics_contexts", @"__invalid_name" ];
ASExperimentalFeatures expected = ASExperimentalGraphicsContexts | ASExperimentalTextNode;
XCTAssertEqual(expected, ASExperimentalFeaturesFromArray(names));
}
@end

View File

@@ -131,7 +131,7 @@
ASDisplayNodeSizeToFitSizeRange(node, ASSizeRangeMake(CGSizeZero, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)));
[node recursivelySetInterfaceState:ASInterfaceStatePreload];
ASCATransactionQueueWait();
ASCATransactionQueueWait(nil);
// No premature view allocation
XCTAssertFalse(node.isNodeLoaded);
// Subnodes should be inserted, laid out and entered preload state

View File

@@ -131,7 +131,7 @@ for (ASDisplayNode *n in @[ nodes ]) {\
- (void)setInterfaceState:(ASInterfaceState)state
{
[super setInterfaceState:state];
ASCATransactionQueueWait();
ASCATransactionQueueWait(nil);
}
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize

View File

@@ -18,7 +18,7 @@
#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASDimension.h>
@class ASDisplayNode;
@class ASCATransactionQueue, ASDisplayNode;
typedef BOOL (^as_condition_block_t)(void);
@@ -28,6 +28,6 @@ BOOL ASDisplayNodeRunRunLoopUntilBlockIsTrue(as_condition_block_t block);
void ASDisplayNodeSizeToFitSize(ASDisplayNode *node, CGSize size);
void ASDisplayNodeSizeToFitSizeRange(ASDisplayNode *node, ASSizeRange sizeRange);
void ASCATransactionQueueWait(void);
void ASCATransactionQueueWait(ASCATransactionQueue *q); // nil means shared queue
ASDISPLAYNODE_EXTERN_C_END

View File

@@ -64,12 +64,13 @@ void ASDisplayNodeSizeToFitSizeRange(ASDisplayNode *node, ASSizeRange sizeRange)
node.bounds = (CGRect){.origin = CGPointZero, .size = sizeThatFits};
}
void ASCATransactionQueueWait(void)
void ASCATransactionQueueWait(ASCATransactionQueue *q)
{
if (!q) { q = ASCATransactionQueue.sharedQueue; }
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:1];
BOOL whileResult = YES;
while ([date timeIntervalSinceNow] > 0 &&
(whileResult = ![[ASCATransactionQueue sharedQueue] isEmpty])) {
(whileResult = ![q isEmpty])) {
[[NSRunLoop currentRunLoop] runUntilDate:
[NSDate dateWithTimeIntervalSinceNow:0.01]];
}

View File

@@ -2,8 +2,12 @@
// ASNetworkImageNodeTests.m
// Texture
//
// Created by Adlai Holler on 10/14/16.
// Copyright © 2016 Facebook. All rights reserved.
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <XCTest/XCTest.h>

View File

@@ -2,8 +2,12 @@
// ASPerformanceTestContext.h
// Texture
//
// Created by Adlai Holler on 8/28/16.
// Copyright © 2016 Facebook. All rights reserved.
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <Foundation/Foundation.h>

View File

@@ -10,7 +10,8 @@
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <XCTest/XCTest.h>
#import "ASTestCase.h"
#import <AsyncDisplayKit/ASRunLoopQueue.h>
#import "ASDisplayNodeTestsHelper.h"
@@ -27,7 +28,7 @@ static NSTimeInterval const kRunLoopRunTime = 0.001; // Allow the RunLoop to run
}
@end
@interface ASRunLoopQueueTests : XCTestCase
@interface ASRunLoopQueueTests : ASTestCase
@end
@@ -171,12 +172,18 @@ static NSTimeInterval const kRunLoopRunTime = 0.001; // Allow the RunLoop to run
- (void)testASCATransactionQueueDisable
{
// Disable coalescing.
ASConfiguration *config = [[ASConfiguration alloc] init];
config.experimentalFeatures = kNilOptions;
[ASConfigurationManager test_resetWithConfiguration:config];
ASCATransactionQueue *queue = [[ASCATransactionQueue alloc] init];
[queue disable];
QueueObject *object = [[QueueObject alloc] init];
[[ASCATransactionQueue sharedQueue] enqueue:object];
XCTAssertFalse(object.queueObjectProcessed);
[queue enqueue:object];
XCTAssertTrue(object.queueObjectProcessed);
XCTAssertTrue([queue isEmpty]);
XCTAssertTrue([queue disabled]);
XCTAssertFalse(queue.enabled);
}
- (void)testASCATransactionQueueProcess
@@ -185,8 +192,9 @@ static NSTimeInterval const kRunLoopRunTime = 0.001; // Allow the RunLoop to run
QueueObject *object = [[QueueObject alloc] init];
[queue enqueue:object];
XCTAssertFalse(object.queueObjectProcessed);
ASCATransactionQueueWait();
ASCATransactionQueueWait(queue);
XCTAssertTrue(object.queueObjectProcessed);
XCTAssertTrue(queue.enabled);
}
@end

View File

@@ -2,8 +2,12 @@
// ASTextNodePerformanceTests.m
// Texture
//
// Created by Adlai Holler on 8/28/16.
// Copyright © 2016 Facebook. All rights reserved.
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <XCTest/XCTest.h>

View File

@@ -17,6 +17,8 @@
#import <CoreText/CoreText.h>
#import "ASTestCase.h"
#import <OCMock/OCMock.h>
#import <AsyncDisplayKit/ASLayout.h>
@@ -31,6 +33,10 @@
@property (nonatomic, copy, readonly) NSString *tappedLinkAttribute;
@property (nonatomic, assign, readonly) id tappedLinkValue;
@end
@interface ASTextNodeSubclass : ASTextNode
@end
@interface ASTextNodeSecondSubclass : ASTextNodeSubclass
@end
@implementation ASTextNodeTestDelegate
@@ -235,4 +241,23 @@
XCTAssertGreaterThan(sizeWithExclusionPaths.height, sizeWithoutExclusionPaths.height, @"Setting exclusions paths should invalidate the calculated size and return a greater size");
}
- (void)testThatTheExperimentWorksCorrectly
{
ASConfiguration *config = [ASConfiguration new];
config.experimentalFeatures = ASExperimentalTextNode;
[ASConfigurationManager test_resetWithConfiguration:config];
ASTextNode *plainTextNode = [[ASTextNode alloc] init];
XCTAssertEqualObjects(plainTextNode.class, [ASTextNode2 class]);
ASTextNodeSecondSubclass *sc2 = [[ASTextNodeSecondSubclass alloc] init];
XCTAssertEqualObjects([ASTextNodeSubclass superclass], [ASTextNode2 class]);
XCTAssertEqualObjects(sc2.superclass, [ASTextNodeSubclass class]);
}
@end
@implementation ASTextNodeSubclass
@end
@implementation ASTextNodeSecondSubclass
@end

View File

@@ -352,7 +352,7 @@
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStatePreload];
[_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys];
ASCATransactionQueueWait();
ASCATransactionQueueWait(nil);
[_videoNode pause];
_videoNode.shouldBePlaying = YES;
XCTAssertFalse(_videoNode.isPlaying);

View File

@@ -2,8 +2,13 @@
// ASTestCase.h
// Texture
//
// Copyright (c) 2017-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// 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 /ASDK-Licenses directory of this source tree. An additional
// grant of patent rights can be found in the PATENTS file in the same directory.
//
// Modifications to this file made after 4/13/2017 are: Copyright (c) through the present,
// Pinterest, Inc. Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
@@ -16,6 +21,7 @@
#import <OCMock/OCMock.h>
#import <AsyncDisplayKit/AsyncDisplayKit.h>
#import "OCMockObject+ASAdditions.h"
#import "ASConfigurationInternal.h"
NS_ASSUME_NONNULL_BEGIN
@@ -25,4 +31,10 @@ NS_ASSUME_NONNULL_BEGIN
@end
@interface ASConfigurationManager (Testing)
+ (void)test_resetWithConfiguration:(nullable ASConfiguration *)configuration;
@end
NS_ASSUME_NONNULL_END

View File

@@ -2,8 +2,13 @@
// ASTestCase.m
// Texture
//
// Copyright (c) 2017-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// 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 /ASDK-Licenses directory of this source tree. An additional
// grant of patent rights can be found in the PATENTS file in the same directory.
//
// Modifications to this file made after 4/13/2017 are: Copyright (c) through the present,
// Pinterest, Inc. Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
@@ -31,6 +36,8 @@ static __weak ASTestCase *currentTestCase;
- (void)tearDown
{
[ASConfigurationManager test_resetWithConfiguration:nil];
// Clear out all application windows. Note: the system will retain these sometimes on its
// own but we'll do our best.
for (UIWindow *window in [UIApplication sharedApplication].windows) {

View File

@@ -36,6 +36,7 @@
CC5532171E15CC1E0011C01F /* ASCollectionSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = CC5532161E15CC1E0011C01F /* ASCollectionSectionController.m */; };
CC6350BB1E1C482D002BC613 /* TailLoadingNode.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6350BA1E1C482D002BC613 /* TailLoadingNode.m */; };
CC85250F1E36B392008EABE6 /* FeedHeaderNode.m in Sources */ = {isa = PBXBuildFile; fileRef = CC85250E1E36B392008EABE6 /* FeedHeaderNode.m */; };
CCEDDDD7200C4C0E00FFCD0A /* TextureConfigDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDD6200C4C0E00FFCD0A /* TextureConfigDelegate.m */; };
E5F128F01E09625400B4335F /* PhotoFeedBaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = E5F128EF1E09625400B4335F /* PhotoFeedBaseController.m */; };
/* End PBXBuildFile section */
@@ -98,6 +99,7 @@
CC6350BA1E1C482D002BC613 /* TailLoadingNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TailLoadingNode.m; sourceTree = "<group>"; };
CC85250D1E36B392008EABE6 /* FeedHeaderNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FeedHeaderNode.h; sourceTree = "<group>"; };
CC85250E1E36B392008EABE6 /* FeedHeaderNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FeedHeaderNode.m; sourceTree = "<group>"; };
CCEDDDD6200C4C0E00FFCD0A /* TextureConfigDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TextureConfigDelegate.m; sourceTree = "<group>"; };
D09B5DF0BFB37583DE8F3142 /* Pods-Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig"; sourceTree = "<group>"; };
E5F128EE1E09612700B4335F /* PhotoFeedBaseController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoFeedBaseController.h; sourceTree = "<group>"; };
E5F128EF1E09625400B4335F /* PhotoFeedBaseController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotoFeedBaseController.m; sourceTree = "<group>"; };
@@ -141,6 +143,7 @@
children = (
768843511CAA37EF00D8629E /* AppDelegate.h */,
768843681CAA37EF00D8629E /* AppDelegate.m */,
CCEDDDD6200C4C0E00FFCD0A /* TextureConfigDelegate.m */,
76229A761CBB79E000B62CEF /* WindowWithStatusBarUnderlay.h */,
76229A771CBB79E000B62CEF /* WindowWithStatusBarUnderlay.m */,
767A5F141CAA3D8A004CDA8D /* Controller */,
@@ -427,6 +430,7 @@
CC5532171E15CC1E0011C01F /* ASCollectionSectionController.m in Sources */,
768843801CAA37EF00D8629E /* AppDelegate.m in Sources */,
768843811CAA37EF00D8629E /* CommentFeedModel.m in Sources */,
CCEDDDD7200C4C0E00FFCD0A /* TextureConfigDelegate.m in Sources */,
7688438E1CAA37EF00D8629E /* PhotoFeedNodeController.m in Sources */,
CC6350BB1E1C482D002BC613 /* TailLoadingNode.m in Sources */,
CC85250F1E36B392008EABE6 /* FeedHeaderNode.m in Sources */,

View File

@@ -7,7 +7,7 @@
// LICENSE file in the /ASDK-Licenses directory of this source tree. An additional
// grant of patent rights can be found in the PATENTS file in the same directory.
//
// Modifications to this file made after 4/13/2017 are: Copyright (c) 2017-present,
// Modifications to this file made after 4/13/2017 are: Copyright (c) through the present,
// Pinterest, Inc. Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -40,8 +40,6 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
ASEnableNoCopyRendering();
// this UIWindow subclass is neccessary to make the status bar opaque
_window = [[WindowWithStatusBarUnderlay alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_window.backgroundColor = [UIColor whiteColor];

View File

@@ -0,0 +1,41 @@
//
// TextureConfigDelegate.m
// Texture
//
// Copyright (c) 2018-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <AsyncDisplayKit/AsyncDisplayKit.h>
@interface TextureConfigDelegate : NSObject <ASConfigurationDelegate>
@end
@implementation ASConfiguration (UserProvided)
+ (ASConfiguration *)textureConfiguration
{
ASConfiguration *config = [[ASConfiguration alloc] init];
config.experimentalFeatures = ASExperimentalGraphicsContexts | ASExperimentalTextNode;
config.delegate = [[TextureConfigDelegate alloc] init];
return config;
}
@end
@implementation TextureConfigDelegate
- (void)textureDidActivateExperimentalFeatures:(ASExperimentalFeatures)features
{
if (features & ASExperimentalGraphicsContexts) {
NSLog(@"Texture activated experimental graphics contexts.");
}
}
@end

View File

@@ -1,18 +1,18 @@
//
// AppDelegate.m
// Sample
// Texture
//
// 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.
// LICENSE file in the /ASDK-Licenses directory of this source tree. An additional
// grant of patent rights can be found in the PATENTS file in the same directory.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Modifications to this file made after 4/13/2017 are: Copyright (c) through the present,
// Pinterest, Inc. Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import "AppDelegate.h"
@@ -24,7 +24,6 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[ASTextNode setExperimentOptions:ASTextNodeExperimentRandomInstances];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];

View File

@@ -1,18 +1,18 @@
//
// ViewController.m
// Sample
// Texture
//
// 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.
// LICENSE file in the /ASDK-Licenses directory of this source tree. An additional
// grant of patent rights can be found in the PATENTS file in the same directory.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Modifications to this file made after 4/13/2017 are: Copyright (c) through the present,
// Pinterest, Inc. Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import "ViewController.h"
@@ -35,12 +35,10 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell
// array of boxed CGSizes corresponding to placekitten.com kittens
NSMutableArray *_kittenDataSource;
BOOL _dataSourceLocked;
NSIndexPath *_blurbNodeIndexPath;
}
@property (nonatomic, strong) NSMutableArray *kittenDataSource;
@property (atomic, assign) BOOL dataSourceLocked;
@end
@@ -96,12 +94,6 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell
return kittens;
}
- (void)setKittenDataSource:(NSMutableArray *)kittenDataSource {
ASDisplayNodeAssert(!self.dataSourceLocked, @"Could not update data source when it is locked !");
_kittenDataSource = kittenDataSource;
}
- (void)toggleEditingMode
{
[_tableNode.view setEditing:!_tableNode.view.editing animated:YES];