diff --git a/.travis.yml b/.travis.yml index 2f5f770720..69217e9a71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: objective-c -osx_image: xcode7.2 +osx_image: xcode7.3 before_install: - brew update - - brew reinstall xctool + - brew reinstall --HEAD xctool - brew reinstall carthage - gem install cocoapods -v 0.38.2 - gem install slather diff --git a/AsyncDisplayKit.podspec b/AsyncDisplayKit.podspec index afec7e166d..2a132397d0 100644 --- a/AsyncDisplayKit.podspec +++ b/AsyncDisplayKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'AsyncDisplayKit' - spec.version = '1.9.7.1' + spec.version = '1.9.8' spec.license = { :type => 'BSD' } spec.homepage = 'http://asyncdisplaykit.org' spec.authors = { 'Scott Goodson' => 'scottgoodson@gmail.com', 'Ryan Nystrom' => 'rnystrom@fb.com' } @@ -14,7 +14,8 @@ Pod::Spec.new do |spec| 'AsyncDisplayKit/Details/**/*.h', 'AsyncDisplayKit/Layout/*.h', 'Base/*.h', - 'AsyncDisplayKit/TextKit/ASTextNodeTypes.h' + 'AsyncDisplayKit/TextKit/ASTextNodeTypes.h', + 'AsyncDisplayKit/TextKit/ASTextKitComponents.h' ] spec.source_files = [ diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index b971702a74..1d77edc23e 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -136,7 +136,7 @@ 254C6B541BF8FF2A003EC431 /* ASTextKitTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 254C6B531BF8FF2A003EC431 /* ASTextKitTests.mm */; }; 254C6B731BF94DF4003EC431 /* ASTextKitCoreTextAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */; }; 254C6B741BF94DF4003EC431 /* ASTextNodeWordKerner.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754B91BEE458E00737CA5 /* ASTextNodeWordKerner.h */; }; - 254C6B751BF94DF4003EC431 /* ASTextKitHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BA1BEE458E00737CA5 /* ASTextKitHelpers.h */; }; + 254C6B751BF94DF4003EC431 /* ASTextKitComponents.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BA1BEE458E00737CA5 /* ASTextKitComponents.h */; settings = {ATTRIBUTES = (Public, ); }; }; 254C6B761BF94DF4003EC431 /* ASTextNodeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; 254C6B771BF94DF4003EC431 /* ASTextKitAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754951BEE44CD00737CA5 /* ASTextKitAttributes.h */; }; 254C6B781BF94DF4003EC431 /* ASTextKitContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754961BEE44CD00737CA5 /* ASTextKitContext.h */; }; @@ -148,7 +148,7 @@ 254C6B7E1BF94DF4003EC431 /* ASTextKitTailTruncater.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754A11BEE44CD00737CA5 /* ASTextKitTailTruncater.h */; }; 254C6B7F1BF94DF4003EC431 /* ASTextKitTruncating.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754A31BEE44CD00737CA5 /* ASTextKitTruncating.h */; }; 254C6B801BF94DF4003EC431 /* ASEqualityHashHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754A41BEE44CD00737CA5 /* ASEqualityHashHelpers.h */; }; - 254C6B821BF94F8A003EC431 /* ASTextKitHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754B71BEE458D00737CA5 /* ASTextKitHelpers.mm */; }; + 254C6B821BF94F8A003EC431 /* ASTextKitComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754B71BEE458D00737CA5 /* ASTextKitComponents.m */; }; 254C6B831BF94F8A003EC431 /* ASTextKitCoreTextAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m */; }; 254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */; }; 254C6B851BF94F8A003EC431 /* ASTextKitAttributes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754941BEE44CD00737CA5 /* ASTextKitAttributes.mm */; }; @@ -179,10 +179,10 @@ 257754B41BEE44CD00737CA5 /* ASTextKitTailTruncater.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754A21BEE44CD00737CA5 /* ASTextKitTailTruncater.mm */; }; 257754B51BEE44CD00737CA5 /* ASTextKitTruncating.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754A31BEE44CD00737CA5 /* ASTextKitTruncating.h */; settings = {ATTRIBUTES = (Public, ); }; }; 257754B61BEE44CD00737CA5 /* ASEqualityHashHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754A41BEE44CD00737CA5 /* ASEqualityHashHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 257754BE1BEE458E00737CA5 /* ASTextKitHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754B71BEE458D00737CA5 /* ASTextKitHelpers.mm */; }; + 257754BE1BEE458E00737CA5 /* ASTextKitComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754B71BEE458D00737CA5 /* ASTextKitComponents.m */; }; 257754BF1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m */; }; 257754C01BEE458E00737CA5 /* ASTextNodeWordKerner.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754B91BEE458E00737CA5 /* ASTextNodeWordKerner.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 257754C11BEE458E00737CA5 /* ASTextKitHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BA1BEE458E00737CA5 /* ASTextKitHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 257754C11BEE458E00737CA5 /* ASTextKitComponents.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BA1BEE458E00737CA5 /* ASTextKitComponents.h */; settings = {ATTRIBUTES = (Public, ); }; }; 257754C21BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 257754C31BEE458E00737CA5 /* ASTextNodeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; 257754C41BEE458E00737CA5 /* ASTextNodeWordKerner.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */; }; @@ -258,6 +258,16 @@ 68EE0DBE1C1B4ED300BA1B99 /* ASMainSerialQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */; }; 68EE0DBF1C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */; }; 68EE0DC01C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */; }; + 698548631CA9E025008A345F /* ASEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 698548611CA9E025008A345F /* ASEnvironment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 698548641CA9E025008A345F /* ASEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 698548611CA9E025008A345F /* ASEnvironment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 698548651CA9E025008A345F /* ASEnvironment.m in Sources */ = {isa = PBXBuildFile; fileRef = 698548621CA9E025008A345F /* ASEnvironment.m */; }; + 698548661CA9E025008A345F /* ASEnvironment.m in Sources */ = {isa = PBXBuildFile; fileRef = 698548621CA9E025008A345F /* ASEnvironment.m */; }; + 698C8B611CAB49FC0052DC3F /* ASLayoutableExtensibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 698C8B601CAB49FC0052DC3F /* ASLayoutableExtensibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 698C8B621CAB49FC0052DC3F /* ASLayoutableExtensibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 698C8B601CAB49FC0052DC3F /* ASLayoutableExtensibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69E1006D1CA89CB600D88C1B /* ASEnvironmentInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */; }; + 69E1006E1CA89CB600D88C1B /* ASEnvironmentInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */; }; + 69E1006F1CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */; }; + 69E100701CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */; }; 69F10C861C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; 69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6BDC61F61979037800E50D21 /* AsyncDisplayKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -288,14 +298,6 @@ 9C55866A1BD549CB00B50E3A /* ASAsciiArtBoxCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.m */; }; 9C55866B1BD54A1900B50E3A /* ASAsciiArtBoxCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.m */; }; 9C55866C1BD54A3000B50E3A /* ASAsciiArtBoxCreator.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5586671BD549CB00B50E3A /* ASAsciiArtBoxCreator.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9C5FA3511B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9C5FA3521B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9C5FA3531B8F6ADF00A62714 /* ASLayoutOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.mm */; }; - 9C5FA3541B8F6ADF00A62714 /* ASLayoutOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.mm */; }; - 9C5FA35F1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA35C1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm */; }; - 9C5FA3601B90C9A500A62714 /* ASLayoutOptionsPrivate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA35C1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm */; }; - 9C65A72A1BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C65A7291BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h */; }; - 9C65A72B1BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C65A7291BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h */; }; 9C6BB3B21B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C6BB3B31B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C8221951BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C8221931BA237B80037F19A /* ASStackBaselinePositionedLayout.h */; }; @@ -377,8 +379,8 @@ B0F8805B1BEAEC7500D17647 /* ASTableNode.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F880591BEAEC7500D17647 /* ASTableNode.m */; }; B13CA0F71C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0F61C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; B13CA0F81C519EBA00E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0F61C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B13CA1001C52004900E031AB /* ASCollectionNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */; }; - B13CA1011C52004900E031AB /* ASCollectionNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */; }; + B13CA1001C52004900E031AB /* ASCollectionNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B13CA1011C52004900E031AB /* ASCollectionNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; B30BF6521C5964B0004FCD53 /* ASLayoutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */; }; B30BF6531C5964B0004FCD53 /* ASLayoutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */; }; B30BF6541C59D889004FCD53 /* ASLayoutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */; }; @@ -712,10 +714,10 @@ 257754A21BEE44CD00737CA5 /* ASTextKitTailTruncater.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitTailTruncater.mm; path = TextKit/ASTextKitTailTruncater.mm; sourceTree = ""; }; 257754A31BEE44CD00737CA5 /* ASTextKitTruncating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitTruncating.h; path = TextKit/ASTextKitTruncating.h; sourceTree = ""; }; 257754A41BEE44CD00737CA5 /* ASEqualityHashHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASEqualityHashHelpers.h; path = TextKit/ASEqualityHashHelpers.h; sourceTree = ""; }; - 257754B71BEE458D00737CA5 /* ASTextKitHelpers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitHelpers.mm; path = TextKit/ASTextKitHelpers.mm; sourceTree = ""; }; + 257754B71BEE458D00737CA5 /* ASTextKitComponents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextKitComponents.m; path = TextKit/ASTextKitComponents.m; sourceTree = ""; }; 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextKitCoreTextAdditions.m; path = TextKit/ASTextKitCoreTextAdditions.m; sourceTree = ""; }; 257754B91BEE458E00737CA5 /* ASTextNodeWordKerner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextNodeWordKerner.h; path = TextKit/ASTextNodeWordKerner.h; sourceTree = ""; }; - 257754BA1BEE458E00737CA5 /* ASTextKitHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitHelpers.h; path = TextKit/ASTextKitHelpers.h; sourceTree = ""; }; + 257754BA1BEE458E00737CA5 /* ASTextKitComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitComponents.h; path = TextKit/ASTextKitComponents.h; sourceTree = ""; }; 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitCoreTextAdditions.h; path = TextKit/ASTextKitCoreTextAdditions.h; sourceTree = ""; }; 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextNodeTypes.h; path = TextKit/ASTextNodeTypes.h; sourceTree = ""; }; 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextNodeWordKerner.m; path = TextKit/ASTextNodeWordKerner.m; sourceTree = ""; }; @@ -740,6 +742,11 @@ 68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+Beta.h"; sourceTree = ""; }; 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMainSerialQueue.h; sourceTree = ""; }; 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMainSerialQueue.mm; sourceTree = ""; }; + 698548611CA9E025008A345F /* ASEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEnvironment.h; sourceTree = ""; }; + 698548621CA9E025008A345F /* ASEnvironment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASEnvironment.m; sourceTree = ""; }; + 698C8B601CAB49FC0052DC3F /* ASLayoutableExtensibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutableExtensibility.h; path = AsyncDisplayKit/Layout/ASLayoutableExtensibility.h; sourceTree = ""; }; + 69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEnvironmentInternal.h; sourceTree = ""; }; + 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEnvironmentInternal.mm; sourceTree = ""; }; 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASRangeControllerUpdateRangeProtocol+Beta.h"; sourceTree = ""; }; 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = ""; }; 764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AsyncDisplayKit+Debug.h"; sourceTree = ""; }; @@ -755,10 +762,6 @@ 9C49C36E1B853957000B0DD5 /* ASStackLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStackLayoutable.h; path = AsyncDisplayKit/Layout/ASStackLayoutable.h; sourceTree = ""; }; 9C5586671BD549CB00B50E3A /* ASAsciiArtBoxCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASAsciiArtBoxCreator.h; path = AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.h; sourceTree = ""; }; 9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASAsciiArtBoxCreator.m; path = AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.m; sourceTree = ""; }; - 9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutOptions.h; path = AsyncDisplayKit/Layout/ASLayoutOptions.h; sourceTree = ""; }; - 9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASLayoutOptions.mm; path = AsyncDisplayKit/Layout/ASLayoutOptions.mm; sourceTree = ""; }; - 9C5FA35C1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASLayoutOptionsPrivate.mm; path = AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.mm; sourceTree = ""; }; - 9C65A7291BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutOptionsPrivate.h; sourceTree = ""; }; 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStaticLayoutable.h; path = AsyncDisplayKit/Layout/ASStaticLayoutable.h; sourceTree = ""; }; 9C8221931BA237B80037F19A /* ASStackBaselinePositionedLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackBaselinePositionedLayout.h; sourceTree = ""; }; 9C8221941BA237B80037F19A /* ASStackBaselinePositionedLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackBaselinePositionedLayout.mm; sourceTree = ""; }; @@ -802,7 +805,7 @@ ACF6ED161B17843500DA7C62 /* ASStackLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStackLayoutSpec.h; path = AsyncDisplayKit/Layout/ASStackLayoutSpec.h; sourceTree = ""; }; ACF6ED171B17843500DA7C62 /* ASStackLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASStackLayoutSpec.mm; path = AsyncDisplayKit/Layout/ASStackLayoutSpec.mm; sourceTree = ""; }; ACF6ED181B17843500DA7C62 /* ASStaticLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStaticLayoutSpec.h; path = AsyncDisplayKit/Layout/ASStaticLayoutSpec.h; sourceTree = ""; }; - ACF6ED191B17843500DA7C62 /* ASStaticLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = ASStaticLayoutSpec.mm; path = AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + ACF6ED191B17843500DA7C62 /* ASStaticLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = ASStaticLayoutSpec.mm; path = AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm; sourceTree = ""; }; ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASInternalHelpers.h; sourceTree = ""; }; ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASInternalHelpers.mm; sourceTree = ""; }; ACF6ED451B17847A00DA7C62 /* ASLayoutSpecUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutSpecUtilities.h; sourceTree = ""; }; @@ -1116,14 +1119,6 @@ 058D09E1195D050800B7D73C /* Details */ = { isa = PBXGroup; children = ( - 25B171EA1C12242700508A7A /* Data Controller */, - 81EE384D1C8E94F000456208 /* ASRunLoopQueue.h */, - 81EE384E1C8E94F000456208 /* ASRunLoopQueue.mm */, - CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */, - CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */, - 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */, - 251B8EF51BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.m */, - 251B8EF61BBB3D690087C538 /* ASDataController+Subclasses.h */, 058D09E2195D050800B7D73C /* _ASDisplayLayer.h */, 058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */, 058D09E4195D050800B7D73C /* _ASDisplayView.h */, @@ -1134,31 +1129,41 @@ 054963481A1EA066000F8E56 /* ASBasicImageDownloader.mm */, 299DA1A71A828D2900162D41 /* ASBatchContext.h */, 299DA1A81A828D2900162D41 /* ASBatchContext.mm */, + 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */, + 251B8EF51BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.m */, 205F0E1B1B373A2C007741D0 /* ASCollectionViewLayoutController.h */, 205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.mm */, + 251B8EF61BBB3D690087C538 /* ASDataController+Subclasses.h */, 05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */, 05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */, + 698548611CA9E025008A345F /* ASEnvironment.h */, + 698548621CA9E025008A345F /* ASEnvironment.m */, 4640521B1A3F83C40061C0BA /* ASFlowLayoutController.h */, 4640521C1A3F83C40061C0BA /* ASFlowLayoutController.mm */, 058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */, 058D09E7195D050800B7D73C /* ASHighlightOverlayLayer.mm */, + 05F20AA31A15733C00DCA68A /* ASImageProtocols.h */, 430E7C8D1B4C23F100697A4C /* ASIndexPath.h */, 430E7C8E1B4C23F100697A4C /* ASIndexPath.m */, - 05F20AA31A15733C00DCA68A /* ASImageProtocols.h */, 4640521D1A3F83C40061C0BA /* ASLayoutController.h */, 292C59991A956527007E5DD6 /* ASLayoutRangeType.h */, 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */, 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */, 058D09E8195D050800B7D73C /* ASMutableAttributedStringBuilder.h */, 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.m */, + CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */, + CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */, 055F1A3619ABD413004DAFF1 /* ASRangeController.h */, 055F1A3719ABD413004DAFF1 /* ASRangeController.mm */, 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */, + 81EE384D1C8E94F000456208 /* ASRunLoopQueue.h */, + 81EE384E1C8E94F000456208 /* ASRunLoopQueue.mm */, 296A0A311A951715005ACEAA /* ASScrollDirection.h */, 205F0E111B371BD7007741D0 /* ASScrollDirection.m */, 058D0A12195D050800B7D73C /* ASThread.h */, 205F0E1F1B376416007741D0 /* CGRect+ASConvenience.h */, 205F0E201B376416007741D0 /* CGRect+ASConvenience.m */, + 25B171EA1C12242700508A7A /* Data Controller */, 058D09F5195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.h */, 058D09F6195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m */, 058D09F7195D050800B7D73C /* Transactions */, @@ -1186,50 +1191,51 @@ 058D0A01195D050800B7D73C /* Private */ = { isa = PBXGroup; 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 */, - 9C8221931BA237B80037F19A /* ASStackBaselinePositionedLayout.h */, - 9C8221941BA237B80037F19A /* ASStackBaselinePositionedLayout.mm */, - 2967F9E11AB0A4CF0072E4AB /* ASBasicImageDownloaderInternal.h */, 058D0A02195D050800B7D73C /* _AS-objc-internal.h */, 058D0A03195D050800B7D73C /* _ASCoreAnimationExtras.h */, 058D0A04195D050800B7D73C /* _ASCoreAnimationExtras.mm */, + AC026B6D1BD57DBF00BBC17E /* _ASHierarchyChangeSet.h */, + AC026B6E1BD57DBF00BBC17E /* _ASHierarchyChangeSet.m */, 058D0A05195D050800B7D73C /* _ASPendingState.h */, 058D0A06195D050800B7D73C /* _ASPendingState.mm */, 058D0A07195D050800B7D73C /* _ASScopeTimer.h */, - 058D0A08195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm */, + DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */, + DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.m */, + 2967F9E11AB0A4CF0072E4AB /* ASBasicImageDownloaderInternal.h */, 044285051BAA63FE00D16268 /* ASBatchFetching.h */, 044285061BAA63FE00D16268 /* ASBatchFetching.m */, + AEB7B0181C5962EA00662EF4 /* ASDefaultPlayButton.h */, + AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */, + 058D0A08195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm */, 058D0A09195D050800B7D73C /* ASDisplayNode+DebugTiming.h */, 058D0A0A195D050800B7D73C /* ASDisplayNode+DebugTiming.mm */, - 058D0A0B195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm */, DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */, + 058D0A0B195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm */, + 058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */, E52405B41C8FEF16004DC8E7 /* ASDisplayNodeLayoutContext.h */, E52405B21C8FEF03004DC8E7 /* ASDisplayNodeLayoutContext.mm */, - 058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */, + 69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */, + 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */, 058D0A0D195D050800B7D73C /* ASImageNode+CGExtras.h */, 058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.m */, - 058D0A10195D050800B7D73C /* ASSentinel.h */, - 058D0A11195D050800B7D73C /* ASSentinel.m */, ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */, ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.mm */, ACF6ED451B17847A00DA7C62 /* ASLayoutSpecUtilities.h */, + 0442850B1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.h */, + 0442850C1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm */, + CC3B20811C3F76D600798563 /* ASPendingStateController.h */, + CC3B20821C3F76D600798563 /* ASPendingStateController.mm */, + 058D0A10195D050800B7D73C /* ASSentinel.h */, + 058D0A11195D050800B7D73C /* ASSentinel.m */, + 9C8221931BA237B80037F19A /* ASStackBaselinePositionedLayout.h */, + 9C8221941BA237B80037F19A /* ASStackBaselinePositionedLayout.mm */, ACF6ED461B17847A00DA7C62 /* ASStackLayoutSpecUtilities.h */, ACF6ED471B17847A00DA7C62 /* ASStackPositionedLayout.h */, ACF6ED481B17847A00DA7C62 /* ASStackPositionedLayout.mm */, ACF6ED491B17847A00DA7C62 /* ASStackUnpositionedLayout.h */, ACF6ED4A1B17847A00DA7C62 /* ASStackUnpositionedLayout.mm */, - 0442850B1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.h */, - 0442850C1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm */, - AEB7B0181C5962EA00662EF4 /* ASDefaultPlayButton.h */, - AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */, + CC3B20871C3F7A5400798563 /* ASWeakSet.h */, + CC3B20881C3F7A5400798563 /* ASWeakSet.m */, DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */, DBC452DA1C5BF64600B16017 /* NSArray+Diffing.m */, ); @@ -1254,11 +1260,11 @@ children = ( B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */, B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */, - 257754B71BEE458D00737CA5 /* ASTextKitHelpers.mm */, + 257754BA1BEE458E00737CA5 /* ASTextKitComponents.h */, + 257754B71BEE458D00737CA5 /* ASTextKitComponents.m */, 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */, 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m */, 257754B91BEE458E00737CA5 /* ASTextNodeWordKerner.h */, - 257754BA1BEE458E00737CA5 /* ASTextKitHelpers.h */, 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */, 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */, 257754941BEE44CD00737CA5 /* ASTextKitAttributes.mm */, @@ -1314,14 +1320,13 @@ ACF6ED041B17843500DA7C62 /* ASCenterLayoutSpec.mm */, ACF6ED071B17843500DA7C62 /* ASDimension.h */, ACF6ED081B17843500DA7C62 /* ASDimension.mm */, - AC47D9431B3BB41900AAEE9D /* ASRelativeSize.h */, - AC47D9441B3BB41900AAEE9D /* ASRelativeSize.mm */, ACF6ED091B17843500DA7C62 /* ASInsetLayoutSpec.h */, ACF6ED0A1B17843500DA7C62 /* ASInsetLayoutSpec.mm */, ACF6ED0B1B17843500DA7C62 /* ASLayout.h */, ACF6ED0C1B17843500DA7C62 /* ASLayout.mm */, ACF6ED111B17843500DA7C62 /* ASLayoutable.h */, E55D86311CA8A14000A0C26F /* ASLayoutable.mm */, + 698C8B601CAB49FC0052DC3F /* ASLayoutableExtensibility.h */, 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */, ACF6ED0D1B17843500DA7C62 /* ASLayoutSpec.h */, ACF6ED0E1B17843500DA7C62 /* ASLayoutSpec.mm */, @@ -1331,6 +1336,8 @@ ACF6ED151B17843500DA7C62 /* ASRatioLayoutSpec.mm */, 7A06A7391C35F08800FE8DAA /* ASRelativeLayoutSpec.h */, 7A06A7381C35F08800FE8DAA /* ASRelativeLayoutSpec.mm */, + AC47D9431B3BB41900AAEE9D /* ASRelativeSize.h */, + AC47D9441B3BB41900AAEE9D /* ASRelativeSize.mm */, 9C49C36E1B853957000B0DD5 /* ASStackLayoutable.h */, AC21EC0F1B3D0BF600C8B19A /* ASStackLayoutDefines.h */, ACF6ED161B17843500DA7C62 /* ASStackLayoutSpec.h */, @@ -1338,9 +1345,6 @@ 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */, ACF6ED181B17843500DA7C62 /* ASStaticLayoutSpec.h */, ACF6ED191B17843500DA7C62 /* ASStaticLayoutSpec.mm */, - 9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */, - 9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.mm */, - 9C5FA35C1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm */, ); name = Layout; path = ..; @@ -1379,6 +1383,8 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 698C8B611CAB49FC0052DC3F /* ASLayoutableExtensibility.h in Headers */, + 698548631CA9E025008A345F /* ASEnvironment.h in Headers */, E5711A2B1C840C81009619D4 /* ASIndexedNodeContext.h in Headers */, 257754C21BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h in Headers */, A373200F1C571B730011FC94 /* ASTextNode+Beta.h in Headers */, @@ -1462,8 +1468,6 @@ 9CDC18CC1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */, B0F8805A1BEAEC7500D17647 /* ASTableNode.h in Headers */, 464052241A3F83C40061C0BA /* ASLayoutController.h in Headers */, - 9C5FA3511B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */, - 9C65A72A1BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h in Headers */, 292C599F1A956527007E5DD6 /* ASLayoutRangeType.h in Headers */, 257754B61BEE44CD00737CA5 /* ASEqualityHashHelpers.h in Headers */, ACF6ED261B17843500DA7C62 /* ASLayoutSpec.h in Headers */, @@ -1487,6 +1491,7 @@ 9C8221951BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */, 257754C31BEE458E00737CA5 /* ASTextNodeTypes.h in Headers */, 9C49C36F1B853957000B0DD5 /* ASStackLayoutable.h in Headers */, + 69E1006D1CA89CB600D88C1B /* ASEnvironmentInternal.h in Headers */, AC21EC101B3D0BF600C8B19A /* ASStackLayoutDefines.h in Headers */, CC7FD9DE1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */, ACF6ED2F1B17843500DA7C62 /* ASStackLayoutSpec.h in Headers */, @@ -1500,7 +1505,7 @@ ACF6ED311B17843500DA7C62 /* ASStaticLayoutSpec.h in Headers */, 055F1A3419ABD3E3004DAFF1 /* ASTableView.h in Headers */, 251B8EF71BBB3D690087C538 /* ASCollectionDataController.h in Headers */, - 257754C11BEE458E00737CA5 /* ASTextKitHelpers.h in Headers */, + 257754C11BEE458E00737CA5 /* ASTextKitComponents.h in Headers */, B30BF6521C5964B0004FCD53 /* ASLayoutManager.h in Headers */, 0574D5E219C110940097DC25 /* ASTableViewProtocols.h in Headers */, 81EE384F1C8E94F000456208 /* ASRunLoopQueue.h in Headers */, @@ -1522,6 +1527,8 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 698C8B621CAB49FC0052DC3F /* ASLayoutableExtensibility.h in Headers */, + 698548641CA9E025008A345F /* ASEnvironment.h in Headers */, AC026B6A1BD57D6F00BBC17E /* ASChangeSetDataController.h in Headers */, B35062481B010EFD0018CF92 /* _AS-objc-internal.h in Headers */, 69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */, @@ -1598,8 +1605,6 @@ 34EFC7691B701CE100AD841F /* ASLayoutable.h in Headers */, 9CDC18CD1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */, B35062201B010EFD0018CF92 /* ASLayoutController.h in Headers */, - 9C5FA3521B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */, - 9C65A72B1BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h in Headers */, B35062211B010EFD0018CF92 /* ASLayoutRangeType.h in Headers */, 34EFC76A1B701CE600AD841F /* ASLayoutSpec.h in Headers */, 34EFC7791B701D3600AD841F /* ASLayoutSpecUtilities.h in Headers */, @@ -1621,7 +1626,7 @@ DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */, 68B0277B1C1A79D60041016B /* ASDisplayNode+Beta.h in Headers */, B350622D1B010EFD0018CF92 /* ASScrollDirection.h in Headers */, - 254C6B751BF94DF4003EC431 /* ASTextKitHelpers.h in Headers */, + 254C6B751BF94DF4003EC431 /* ASTextKitComponents.h in Headers */, B35062081B010EFD0018CF92 /* ASScrollNode.h in Headers */, 25E327571C16819500A2170C /* ASPagerNode.h in Headers */, B35062551B010EFD0018CF92 /* ASSentinel.h in Headers */, @@ -1640,6 +1645,7 @@ 92DD2FE81BF4D0A80074C9DD /* ASMapNode.h in Headers */, 044284FE1BAA387800D16268 /* ASStackLayoutSpecUtilities.h in Headers */, 34EFC7751B701D2400AD841F /* ASStackPositionedLayout.h in Headers */, + 69E1006E1CA89CB600D88C1B /* ASEnvironmentInternal.h in Headers */, 34EFC7771B701D2D00AD841F /* ASStackUnpositionedLayout.h in Headers */, 9C6BB3B31B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */, 34EFC7731B701D0700AD841F /* ASStaticLayoutSpec.h in Headers */, @@ -1741,6 +1747,7 @@ 058D09A4195D04C000B7D73C /* Project object */ = { isa = PBXProject; attributes = { + CLASSPREFIX = AS; LastUpgradeCheck = 0720; ORGANIZATIONNAME = Facebook; TargetAttributes = { @@ -1872,6 +1879,7 @@ DBDB83961C6E879900D0098C /* ASPagerFlowLayout.m in Sources */, 058D0A26195D050800B7D73C /* _ASCoreAnimationExtras.mm in Sources */, 257754B41BEE44CD00737CA5 /* ASTextKitTailTruncater.mm in Sources */, + 69E1006F1CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */, AC026B711BD57DBF00BBC17E /* _ASHierarchyChangeSet.m in Sources */, 257754BF1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m in Sources */, 058D0A18195D050800B7D73C /* _ASDisplayLayer.mm in Sources */, @@ -1915,10 +1923,9 @@ 430E7C911B4C23F100697A4C /* ASIndexPath.m in Sources */, ACF6ED231B17843500DA7C62 /* ASInsetLayoutSpec.mm in Sources */, ACF6ED4C1B17847A00DA7C62 /* ASInternalHelpers.mm in Sources */, + 698548651CA9E025008A345F /* ASEnvironment.m in Sources */, ACF6ED251B17843500DA7C62 /* ASLayout.mm in Sources */, DB55C2631C6408D6004EDCF5 /* _ASTransitionContext.m in Sources */, - 9C5FA3531B8F6ADF00A62714 /* ASLayoutOptions.mm in Sources */, - 9C5FA35F1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm in Sources */, 251B8EFA1BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.m in Sources */, ACF6ED271B17843500DA7C62 /* ASLayoutSpec.mm in Sources */, 257754B01BEE44CD00737CA5 /* ASTextKitRenderer+TextChecking.mm in Sources */, @@ -1947,7 +1954,7 @@ 9C8221971BA237B80037F19A /* ASStackBaselinePositionedLayout.mm in Sources */, 251B8EF81BBB3D690087C538 /* ASCollectionDataController.mm in Sources */, ACF6ED301B17843500DA7C62 /* ASStackLayoutSpec.mm in Sources */, - 257754BE1BEE458E00737CA5 /* ASTextKitHelpers.mm in Sources */, + 257754BE1BEE458E00737CA5 /* ASTextKitComponents.m in Sources */, 257754A91BEE44CD00737CA5 /* ASTextKitContext.mm in Sources */, ACF6ED501B17847A00DA7C62 /* ASStackPositionedLayout.mm in Sources */, ACF6ED521B17847A00DA7C62 /* ASStackUnpositionedLayout.mm in Sources */, @@ -2026,6 +2033,7 @@ B35062421B010EFD0018CF92 /* _ASAsyncTransactionGroup.m in Sources */, B350624A1B010EFD0018CF92 /* _ASCoreAnimationExtras.mm in Sources */, 68EE0DC01C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */, + 698548661CA9E025008A345F /* ASEnvironment.m in Sources */, 2767E9421BB19BD600EA9B77 /* ASViewController.m in Sources */, B35062101B010EFD0018CF92 /* _ASDisplayLayer.mm in Sources */, 9C55866B1BD54A1900B50E3A /* ASAsciiArtBoxCreator.m in Sources */, @@ -2055,6 +2063,7 @@ 636EA1A41C7FF4EC00EE152F /* NSArray+Diffing.m in Sources */, B35062501B010EFD0018CF92 /* ASDisplayNode+DebugTiming.mm in Sources */, DEC146B91C37A16A004A0EE7 /* ASCollectionInternal.m in Sources */, + 69E100701CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */, 254C6B891BF94F8A003EC431 /* ASTextKitRenderer+Positioning.mm in Sources */, E5711A301C840C96009619D4 /* ASIndexedNodeContext.m in Sources */, B35062511B010EFD0018CF92 /* ASDisplayNode+UIViewBridge.mm in Sources */, @@ -2067,13 +2076,11 @@ B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */, B35062541B010EFD0018CF92 /* ASImageNode+CGExtras.m in Sources */, B35062031B010EFD0018CF92 /* ASImageNode.mm in Sources */, - 254C6B821BF94F8A003EC431 /* ASTextKitHelpers.mm in Sources */, + 254C6B821BF94F8A003EC431 /* ASTextKitComponents.m in Sources */, 430E7C921B4C23F100697A4C /* ASIndexPath.m in Sources */, 34EFC7601B701C8B00AD841F /* ASInsetLayoutSpec.mm in Sources */, 34EFC75E1B701BF000AD841F /* ASInternalHelpers.mm in Sources */, 34EFC7681B701CDE00AD841F /* ASLayout.mm in Sources */, - 9C5FA3541B8F6ADF00A62714 /* ASLayoutOptions.mm in Sources */, - 9C5FA3601B90C9A500A62714 /* ASLayoutOptionsPrivate.mm in Sources */, DECBD6EA1BE56E1900CF4905 /* ASButtonNode.mm in Sources */, 254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.m in Sources */, 34EFC76B1B701CEB00AD841F /* ASLayoutSpec.mm in Sources */, diff --git a/AsyncDisplayKit/ASControlNode.mm b/AsyncDisplayKit/ASControlNode.mm index 247752d523..dd576f5ae5 100644 --- a/AsyncDisplayKit/ASControlNode.mm +++ b/AsyncDisplayKit/ASControlNode.mm @@ -500,5 +500,4 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v _enableHitTestDebug = enable; } - @end diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index ae7fff8f64..0d0b362b85 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -10,7 +10,6 @@ #import "ASDisplayNode+Subclasses.h" #import "ASDisplayNode+FrameworkPrivate.h" #import "ASDisplayNode+Beta.h" -#import "ASLayoutOptionsPrivate.h" #import #import @@ -25,6 +24,7 @@ #import "ASDisplayNodeExtras.h" #import "ASEqualityHelpers.h" #import "ASRunLoopQueue.h" +#import "ASEnvironmentInternal.h" #import "ASInternalHelpers.h" #import "ASLayout.h" @@ -60,7 +60,7 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS @implementation ASDisplayNode // these dynamic properties all defined in ASLayoutOptionsPrivate.m -@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition, layoutOptions; +@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition; @synthesize name = _name; @synthesize preferredFrameSize = _preferredFrameSize; @synthesize isFinalLayoutable = _isFinalLayoutable; @@ -252,6 +252,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) _contentsScaleForDisplay = ASScreenScale(); _displaySentinel = [[ASSentinel alloc] init]; _preferredFrameSize = CGSizeZero; + + _environmentState = ASEnvironmentStateMakeDefault(); } - (id)init @@ -630,9 +632,11 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) return NO; } - if (ASHierarchyStateIncludesLayoutPending(_hierarchyState) - && _pendingTransitionID != ASLayoutableGetCurrentContext().transitionID) { - return NO; + if (ASHierarchyStateIncludesLayoutPending(_hierarchyState)) { + ASLayoutableContext context = ASLayoutableGetCurrentContext(); + if (ASLayoutableContextIsNull(context) || _pendingTransitionID != context.transitionID) { + return NO; + } } // only calculate the size if @@ -1596,6 +1600,8 @@ static NSInteger incrementIfFound(NSInteger i) { if (_flags.shouldRasterizeDescendants) { // Nodes that are descendants of a rasterized container do not have views or layers, and so cannot receive visibility notifications directly via orderIn/orderOut CALayer actions. Manually send visibility notifications to rasterized descendants. [self _recursiveDidExitHierarchy]; + } else { + [self didExitHierarchy]; } // This case is important when tearing down hierarchies. We must deliver a visibilityDidChange:NO callback, as part our API guarantee that this method can be used for @@ -1614,7 +1620,6 @@ static NSInteger incrementIfFound(NSInteger i) { }); } - [self didExitHierarchy]; _flags.isExitingHierarchy = NO; } } @@ -1697,6 +1702,10 @@ static NSInteger incrementIfFound(NSInteger i) { [self exitHierarchyState:stateToEnterOrExit]; } } + + if ([newSupernode supportsUpwardPropagation]) { + ASEnvironmentStatePropagateUp(newSupernode, _environmentState.layoutOptionsState); + } } // Track that a node will be displayed as part of the current node hierarchy. @@ -1851,6 +1860,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) ASDN::MutexLocker l(_propertyLock); if (_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) { ASLayoutSpec *layoutSpec = [self layoutSpecThatFits:constrainedSize]; + layoutSpec.parent = self; layoutSpec.isMutable = NO; ASLayout *layout = [layoutSpec measureWithSizeRange:constrainedSize]; // Make sure layoutableObject of the root layout is `self`, so that the flattened layout will be structurally correct. @@ -1915,6 +1925,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) ASDN::MutexLocker l(_propertyLock); if (! CGSizeEqualToSize(_preferredFrameSize, preferredFrameSize)) { _preferredFrameSize = preferredFrameSize; + self.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(_preferredFrameSize), ASRelativeSizeMakeWithCGSize(_preferredFrameSize)); [self invalidateCalculatedLayout]; } } @@ -2225,7 +2236,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) // Leaving layout pending state, reset related properties { ASDN::MutexLocker l(_propertyLock); - _pendingTransitionID = 0; + _pendingTransitionID = ASLayoutableContextInvalidTransitionID; _pendingLayoutContext = nil; } } @@ -2383,13 +2394,11 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) return [superview gestureRecognizerShouldBegin:gestureRecognizer]; } -#if DEBUG - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { ASDisplayNodeAssertMainThread(); return [_view hitTest:point withEvent:event]; } -#endif - (void)setHitTestSlop:(UIEdgeInsets)hitTestSlop { @@ -2665,6 +2674,37 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority"; return self; } +#pragma mark - ASEnvironment + +- (ASEnvironmentState)environmentState +{ + return _environmentState; +} + +- (void)setEnvironmentState:(ASEnvironmentState)environmentState +{ + _environmentState = environmentState; +} + +- (ASDisplayNode *)parent +{ + return self.supernode; +} + +- (NSArray *)children +{ + return self.subnodes; +} + +- (BOOL)supportsUpwardPropagation +{ + return YES; +} + +ASEnvironmentLayoutOptionsForwarding +ASEnvironmentLayoutExtensibilityForwarding + + #if TARGET_OS_TV #pragma mark - UIFocusEnvironment Protocol (tvOS) diff --git a/AsyncDisplayKit/ASEditableTextNode.h b/AsyncDisplayKit/ASEditableTextNode.h index 31e39aa60e..22ba5822a0 100644 --- a/AsyncDisplayKit/ASEditableTextNode.h +++ b/AsyncDisplayKit/ASEditableTextNode.h @@ -7,6 +7,7 @@ */ #import +#import NS_ASSUME_NONNULL_BEGIN @@ -18,6 +19,24 @@ NS_ASSUME_NONNULL_BEGIN */ @interface ASEditableTextNode : ASDisplayNode +/** + * @abstract Initializes an editable text node using default TextKit components. + * + * @returns An initialized ASEditableTextNode. + */ +- (instancetype)init; + +/** + * @abstract Initializes an editable text node using the provided TextKit components. + * + * @param textKitComponents The TextKit stack used to render text. + * @param placeholderTextKitComponents The TextKit stack used to render placeholder text. + * + * @returns An initialized ASEditableTextNode. + */ +- (instancetype)initWithTextKitComponents:(ASTextKitComponents *)textKitComponents + placeholderTextKitComponents:(ASTextKitComponents *)placeholderTextKitComponents; + //! @abstract The text node's delegate, which must conform to the protocol. @property (nonatomic, readwrite, weak) id delegate; diff --git a/AsyncDisplayKit/ASEditableTextNode.mm b/AsyncDisplayKit/ASEditableTextNode.mm index cfa338b4db..ba0b0b1f99 100644 --- a/AsyncDisplayKit/ASEditableTextNode.mm +++ b/AsyncDisplayKit/ASEditableTextNode.mm @@ -12,7 +12,6 @@ #import "ASDisplayNode+Subclasses.h" #import "ASEqualityHelpers.h" -#import "ASTextKitHelpers.h" #import "ASTextNodeWordKerner.h" #import "ASThread.h" @@ -45,6 +44,8 @@ - (void)setScrollEnabled:(BOOL)scrollEnabled { _shouldBlockPanGesture = !scrollEnabled; + self.scrollsToTop = scrollEnabled; + [super setScrollEnabled:YES]; } @@ -93,6 +94,13 @@ #pragma mark - NSObject Overrides - (instancetype)init +{ + return [self initWithTextKitComponents:[ASTextKitComponents componentsWithAttributedSeedString:nil textContainerSize:CGSizeZero] + placeholderTextKitComponents:[ASTextKitComponents componentsWithAttributedSeedString:nil textContainerSize:CGSizeZero]]; +} + +- (instancetype)initWithTextKitComponents:(ASTextKitComponents *)textKitComponents + placeholderTextKitComponents:(ASTextKitComponents *)placeholderTextKitComponents { if (!(self = [super init])) return nil; @@ -101,14 +109,14 @@ _scrollEnabled = YES; // Create the scaffolding for the text view. - _textKitComponents = [ASTextKitComponents componentsWithAttributedSeedString:nil textContainerSize:CGSizeZero]; + _textKitComponents = textKitComponents; _textKitComponents.layoutManager.delegate = self; _wordKerner = [[ASTextNodeWordKerner alloc] init]; _returnKeyType = UIReturnKeyDefault; _textContainerInset = UIEdgeInsetsZero; // Create the placeholder scaffolding. - _placeholderTextKitComponents = [ASTextKitComponents componentsWithAttributedSeedString:nil textContainerSize:CGSizeZero]; + _placeholderTextKitComponents = placeholderTextKitComponents; _placeholderTextKitComponents.layoutManager.delegate = self; return self; diff --git a/AsyncDisplayKit/ASTextNode+Beta.h b/AsyncDisplayKit/ASTextNode+Beta.h index 5cf43aa5ad..564f5d1917 100644 --- a/AsyncDisplayKit/ASTextNode+Beta.h +++ b/AsyncDisplayKit/ASTextNode+Beta.h @@ -6,6 +6,7 @@ // Copyright © 2016 Facebook. All rights reserved. // +NS_ASSUME_NONNULL_BEGIN @interface ASTextNode () @@ -13,18 +14,19 @@ @abstract An array of descending scale factors that will be applied to this text node to try to make it fit within its constrained size @default nil (no scaling) */ -@property (nonatomic, copy) NSArray *pointSizeScaleFactors; +@property (nullable, nonatomic, copy) NSArray *pointSizeScaleFactors; #pragma mark - ASTextKit Customization /** A block to provide a hook to provide a custom NSLayoutManager to the ASTextKitRenderer */ -@property (nonatomic, copy) NSLayoutManager * (^layoutManagerCreationBlock)(void); +@property (nullable, nonatomic, copy) NSLayoutManager * (^layoutManagerCreationBlock)(void); /** - A block to provide a hook to provide a NSTextStorage to the Text Kit's layout manager. + A block to provide a hook to provide a NSTextStorage to the TextKit's layout manager. */ -@property (nonatomic, copy) NSTextStorage * (^textStorageCreationBlock)(NSAttributedString *attributedString); +@property (nullable, nonatomic, copy) NSTextStorage * (^textStorageCreationBlock)(NSAttributedString *_Nullable attributedString); +@end -@end \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASTextNode.mm b/AsyncDisplayKit/ASTextNode.mm index 8c59739588..8ec7a77a20 100644 --- a/AsyncDisplayKit/ASTextNode.mm +++ b/AsyncDisplayKit/ASTextNode.mm @@ -17,7 +17,7 @@ #import #import "ASTextKitCoreTextAdditions.h" -#import "ASTextKitHelpers.h" +#import "ASTextKitComponents.h" #import "ASTextKitFontSizeAdjuster.h" #import "ASTextKitRenderer.h" #import "ASTextKitRenderer+Positioning.h" @@ -364,6 +364,12 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; } _attributedString = ASCleanseAttributedStringOfCoreTextAttributes(attributedString); + + if (_attributedString.length > 0) { + CGFloat screenScale = ASScreenScale(); + self.ascender = round([[_attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale; + self.descender = round([[_attributedString attribute:NSFontAttributeName atIndex:_attributedString.length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale; + } // Sync the truncation string with attributes from the updated _attributedString // Without this, the size calculation of the text with truncation applied will diff --git a/AsyncDisplayKit/AsyncDisplayKit.h b/AsyncDisplayKit/AsyncDisplayKit.h index 967810ed00..54c34b5813 100644 --- a/AsyncDisplayKit/AsyncDisplayKit.h +++ b/AsyncDisplayKit/AsyncDisplayKit.h @@ -15,7 +15,6 @@ #import #import #import - #import #import @@ -41,6 +40,7 @@ #import #import +#import #import #import #import @@ -68,7 +68,6 @@ #import #import #import -#import #import #import #import @@ -77,5 +76,8 @@ #import #import #import +#import #import + +#import diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index a879099aff..e5ddc276d4 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -129,15 +129,10 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; - (void)layoutLoadedNodes:(NSArray *)nodes fromContexts:(NSArray *)contexts ofKind:(NSString *)kind { - NSAssert(NSThread.isMainThread, @"Main thread layout must be on the main thread."); + NSAssert(ASDisplayNodeThreadIsMain(), @"Layout of loaded nodes must happen on the main thread."); ASDisplayNodeAssertTrue(nodes.count == contexts.count); - [contexts enumerateObjectsUsingBlock:^(ASIndexedNodeContext *context, NSUInteger idx, __unused BOOL * stop) { - ASCellNode *node = nodes[idx]; - if (node.isNodeLoaded) { - [self _layoutNode:node withConstrainedSize:context.constrainedSize]; - } - }]; + [self _layoutNodes:nodes fromContexts:contexts inIndexesOfRange:NSMakeRange(0, nodes.count) ofKind:kind]; } /** @@ -160,9 +155,31 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; }]; } +/** + * Perform measurement and layout of loaded or unloaded nodes based if they will be layed out on main thread or not + */ +- (void)_layoutNodes:(NSArray *)nodes fromContexts:(NSArray *)contexts inIndexesOfRange:(NSRange)range ofKind:(NSString *)kind +{ + if (_dataSource == nil) { + return; + } + + // For any given layout pass that occurs, this method will be called at least twice, once on the main thread and + // the background, to result in complete coverage of both loaded and unloaded nodes + BOOL isMainThread = ASDisplayNodeThreadIsMain(); + for (NSUInteger k = range.location; k < NSMaxRange(range); k++) { + ASCellNode *node = nodes[k]; + // Only nodes that are loaded should be layout on the main thread + if (node.isNodeLoaded == isMainThread) { + ASIndexedNodeContext *context = contexts[k]; + [self _layoutNode:node withConstrainedSize:context.constrainedSize]; + } + } +} + - (void)_layoutNodesFromContexts:(NSArray *)contexts ofKind:(NSString *)kind completion:(ASDataControllerCompletionBlock)completionBlock { - if (!contexts.count) { + if (!contexts.count || _dataSource == nil) { return; } @@ -200,25 +217,30 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - [self layoutLoadedNodes:subarray fromContexts:[contexts subarrayWithRange:NSMakeRange(j, batchCount)] ofKind:kind]; + + [self _layoutNodes:subarray + fromContexts:contexts + inIndexesOfRange:NSMakeRange(0, batchCount) + ofKind:kind]; + } else { allocationBlock(); [_mainSerialQueue performBlockOnMainThread:^{ - [self layoutLoadedNodes:subarray fromContexts:[contexts subarrayWithRange:NSMakeRange(j, batchCount)] ofKind:kind]; + [self _layoutNodes:subarray + fromContexts:contexts + inIndexesOfRange:NSMakeRange(0, batchCount) + ofKind:kind]; }]; } [allocatedNodes addObjectsFromArray:subarray]; dispatch_group_async(layoutGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - for (NSUInteger k = j; k < j + batchCount; k++) { - ASCellNode *node = allocatedNodes[k]; - // Only measure nodes whose views aren't loaded, since we're in the background. - // We should already have measured loaded nodes before we left the main thread, using layoutLoadedNodes:ofKind:atIndexPaths: - if (!node.isNodeLoaded) { - [self _layoutNode:node withConstrainedSize:contexts[k].constrainedSize]; - } - } + // We should already have measured loaded nodes before we left the main thread. Layout the remaining once on a background thread. + [self _layoutNodes:allocatedNodes + fromContexts:contexts + inIndexesOfRange:NSMakeRange(j, batchCount) + ofKind:kind]; }); } @@ -244,7 +266,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; - (void)insertNodes:(NSArray *)nodes ofKind:(NSString *)kind atIndexPaths:(NSArray *)indexPaths completion:(ASDataControllerCompletionBlock)completionBlock { - if (indexPaths.count == 0) { + if (!indexPaths.count || _dataSource == nil) { return; } @@ -265,7 +287,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; - (void)deleteNodesOfKind:(NSString *)kind atIndexPaths:(NSArray *)indexPaths completion:(ASDataControllerCompletionBlock)completionBlock { - if (indexPaths.count == 0) { + if (!indexPaths.count || _dataSource == nil) { return; } @@ -285,8 +307,9 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; - (void)insertSections:(NSMutableArray *)sections ofKind:(NSString *)kind atIndexSet:(NSIndexSet *)indexSet completion:(void (^)(NSArray *sections, NSIndexSet *indexSet))completionBlock { - if (indexSet.count == 0) + if (!indexSet.count|| _dataSource == nil) { return; + } if (_editingNodes[kind] == nil) { _editingNodes[kind] = [NSMutableArray array]; @@ -307,8 +330,10 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; - (void)deleteSectionsOfKind:(NSString *)kind atIndexSet:(NSIndexSet *)indexSet completion:(void (^)(NSIndexSet *indexSet))completionBlock { - if (indexSet.count == 0) + if (!indexSet.count || _dataSource == nil) { return; + } + [_editingNodes[kind] removeObjectsAtIndexes:indexSet]; [_mainSerialQueue performBlockOnMainThread:^{ [_completedNodes[kind] removeObjectsAtIndexes:indexSet]; @@ -328,9 +353,6 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; */ - (void)_insertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { - if (indexPaths.count == 0) { - return; - } [self insertNodes:nodes ofKind:ASDataControllerRowNodeKind atIndexPaths:indexPaths completion:^(NSArray *nodes, NSArray *indexPaths) { if (_delegateDidInsertNodes) [_delegate dataController:self didInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; @@ -345,9 +367,6 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; */ - (void)_deleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { - if (indexPaths.count == 0) { - return; - } [self deleteNodesOfKind:ASDataControllerRowNodeKind atIndexPaths:indexPaths completion:^(NSArray *nodes, NSArray *indexPaths) { if (_delegateDidDeleteNodes) [_delegate dataController:self didDeleteNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; diff --git a/AsyncDisplayKit/Details/ASEnvironment.h b/AsyncDisplayKit/Details/ASEnvironment.h new file mode 100644 index 0000000000..20837d4aa4 --- /dev/null +++ b/AsyncDisplayKit/Details/ASEnvironment.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import + +#import "ASDimension.h" +#import "ASStackLayoutDefines.h" +#import "ASRelativeSize.h" + + +ASDISPLAYNODE_EXTERN_C_BEGIN +NS_ASSUME_NONNULL_BEGIN + +static const int kMaxEnvironmentStateBoolExtensions = 1; +static const int kMaxEnvironmentStateIntegerExtensions = 4; +static const int kMaxEnvironmentStateEdgeInsetExtensions = 1; + +#pragma mark - + +typedef struct ASEnvironmentStateExtensions { + // Values to store extensions + BOOL boolExtensions[kMaxEnvironmentStateBoolExtensions]; + NSInteger integerExtensions[kMaxEnvironmentStateIntegerExtensions]; + UIEdgeInsets edgeInsetsExtensions[kMaxEnvironmentStateEdgeInsetExtensions]; +} ASEnvironmentStateExtensions; + +#pragma mark - ASEnvironmentLayoutOptionsState + +typedef struct ASEnvironmentLayoutOptionsState { + CGFloat spacingBefore;// = 0; + CGFloat spacingAfter;// = 0; + BOOL flexGrow;// = NO; + BOOL flexShrink;// = NO; + ASRelativeDimension flexBasis;// = ASRelativeDimensionUnconstrained; + ASStackLayoutAlignSelf alignSelf;// = ASStackLayoutAlignSelfAuto; + CGFloat ascender;// = 0; + CGFloat descender;// = 0; + + ASRelativeSizeRange sizeRange;// = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMakeWithCGSize(CGSizeZero));; + CGPoint layoutPosition;// = CGPointZero; + + ASEnvironmentStateExtensions _extensions; +} ASEnvironmentLayoutOptionsState; + + +#pragma mark - ASEnvironmentHierarchyState + +typedef struct ASEnvironmentHierarchyState { + unsigned rasterized:1; // = NO + unsigned rangeManaged:1; // = NO + unsigned transitioningSupernodes:1; // = NO + unsigned layoutPending:1; // = NO +} ASEnvironmentHierarchyState; + + +#pragma mark - ASEnvironmentState + +typedef struct ASEnvironmentState { + struct ASEnvironmentHierarchyState hierarchyState; + struct ASEnvironmentLayoutOptionsState layoutOptionsState; +} ASEnvironmentState; +extern ASEnvironmentState ASEnvironmentStateMakeDefault(); + +ASDISPLAYNODE_EXTERN_C_END + + +#pragma mark - ASEnvironment + +/** + * ASEnvironment allows objects that conform to the ASEnvironment protocol to be able to propagate specific States + * defined in an ASEnvironmentState up and down the ASEnvironment tree. To be able to define how merges of + * States should happen, specific merge functions can be provided + */ +@protocol ASEnvironment + +/// The environment collection of an object which class conforms to the ASEnvironment protocol +- (ASEnvironmentState)environmentState; +- (void)setEnvironmentState:(ASEnvironmentState)environmentState; + +/// Returns the parent of an object which class conforms to the ASEnvironment protocol +- (id _Nullable)parent; + +/// Returns all children of an object which class conforms to the ASEnvironment protocol +- (NSArray> *)children; + +/// Classes should implement this method and return YES / NO dependent if upward propagation is enabled or not +- (BOOL)supportsUpwardPropagation; + +@end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASEnvironment.m b/AsyncDisplayKit/Details/ASEnvironment.m new file mode 100644 index 0000000000..f3b2039f8f --- /dev/null +++ b/AsyncDisplayKit/Details/ASEnvironment.m @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import "ASEnvironment.h" + +ASEnvironmentLayoutOptionsState _ASEnvironmentLayoutOptionsStateMakeDefault() +{ + return (ASEnvironmentLayoutOptionsState) { + // Default values can be defined in here + }; +} + +ASEnvironmentHierarchyState _ASEnvironmentHierarchyStateMakeDefault() +{ + return (ASEnvironmentHierarchyState) { + // Default values can be defined in here + }; +} + +ASEnvironmentState ASEnvironmentStateMakeDefault() +{ + return (ASEnvironmentState) { + .layoutOptionsState = _ASEnvironmentLayoutOptionsStateMakeDefault(), + .hierarchyState = _ASEnvironmentHierarchyStateMakeDefault() + }; +} \ No newline at end of file diff --git a/AsyncDisplayKit/Layout/ASLayoutOptions.h b/AsyncDisplayKit/Layout/ASLayoutOptions.h deleted file mode 100644 index fbc50bf8e3..0000000000 --- a/AsyncDisplayKit/Layout/ASLayoutOptions.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ - -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol ASLayoutable; - -/** - * A store for all of the options defined by ASLayoutSpec subclasses. All implementors of ASLayoutable own a - * ASLayoutOptions. When certain layoutSpecs need option values, they are read from this class. - * - * Unless you wish to create a custom layout spec, ASLayoutOptions can largely be ignored. Instead you can access - * the layout option properties exposed in ASLayoutable directly, which will set the values in ASLayoutOptions - * behind the scenes. - */ -@interface ASLayoutOptions : NSObject - -/** - * Sets the class name for the ASLayoutOptions subclasses that will be created when a node or layoutSpec's options - * are first accessed. - * - * If you create a custom layoutSpec that includes new options, you will want to subclass ASLayoutOptions to add - * the new layout options for your layoutSpec(s). In order to make sure your subclass is created instead of an - * instance of ASLayoutOptions, call setDefaultLayoutOptionsClass: early in app launch (applicationDidFinishLaunching:) - * with your subclass's class. - * - * @param defaultLayoutOptionsClass The class of ASLayoutOptions that will be lazily created for a node or layout spec. - */ -+ (void)setDefaultLayoutOptionsClass:(Class)defaultLayoutOptionsClass; - -/** - * @return the Class of ASLayoutOptions that will be created for a node or layoutspec. Defaults to [ASLayoutOptions class]; - */ -+ (Class)defaultLayoutOptionsClass; - -#pragma mark - Subclasses should implement these! -/** - * Initializes a new ASLayoutOptions using the given layoutable to assign any intrinsic option values. - * This init function sets a sensible default value for each layout option. If you create a subclass of - * ASLayoutOptions, your subclass should do the same. - * - * @param layoutable The layoutable that will own these options. The layoutable will be used to set any intrinsic - * layoutOptions. For example, if the layoutable is an ASTextNode the ascender/descender values will get set. - * - * @return a new instance of ASLayoutOptions - */ -- (instancetype)initWithLayoutable:(id)layoutable; - -/** - * Copies the values of layoutOptions into self. This is useful when placing a layoutable inside of another. Consider - * an ASTextNode that you want to align to the baseline by putting it in an ASStackLayoutSpec. Before that, you want - * to inset the ASTextNode by placing it in an ASInsetLayoutSpec. An ASInsetLayoutSpec will not have any information - * about the ASTextNode's ascender/descender unless we copy over the layout options from ASTextNode to ASInsetLayoutSpec. - * This is done automatically and should not need to be called directly. It is listed here to make sure that any - * ASLayoutOptions subclass implements the method. - * - * @param layoutOptions The layoutOptions to copy from - */ -- (void)copyFromOptions:(ASLayoutOptions *)layoutOptions; - -#pragma mark - ASStackLayoutable - -@property (nonatomic, readwrite) CGFloat spacingBefore; -@property (nonatomic, readwrite) CGFloat spacingAfter; -@property (nonatomic, readwrite) BOOL flexGrow; -@property (nonatomic, readwrite) BOOL flexShrink; -@property (nonatomic, readwrite) ASRelativeDimension flexBasis; -@property (nonatomic, readwrite) ASStackLayoutAlignSelf alignSelf; -@property (nonatomic, readwrite) CGFloat ascender; -@property (nonatomic, readwrite) CGFloat descender; - -#pragma mark - ASStaticLayoutable - -@property (nonatomic, readwrite) ASRelativeSizeRange sizeRange; -@property (nonatomic, readwrite) CGPoint layoutPosition; - -@end - -NS_ASSUME_NONNULL_END - diff --git a/AsyncDisplayKit/Layout/ASLayoutOptions.mm b/AsyncDisplayKit/Layout/ASLayoutOptions.mm deleted file mode 100644 index ad503014bf..0000000000 --- a/AsyncDisplayKit/Layout/ASLayoutOptions.mm +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ - -#import "ASLayoutOptions.h" - -#import -#import -#import -#import "ASInternalHelpers.h" - -@interface ASLayoutOptions() -{ - ASDN::RecursiveMutex _propertyLock; -} -@end - -@implementation ASLayoutOptions - -@synthesize spacingBefore = _spacingBefore; -@synthesize spacingAfter = _spacingAfter; -@synthesize flexGrow = _flexGrow; -@synthesize flexShrink = _flexShrink; -@synthesize flexBasis = _flexBasis; -@synthesize alignSelf = _alignSelf; - -@synthesize ascender = _ascender; -@synthesize descender = _descender; - -@synthesize sizeRange = _sizeRange; -@synthesize layoutPosition = _layoutPosition; - -static Class gDefaultLayoutOptionsClass = nil; -+ (void)setDefaultLayoutOptionsClass:(Class)defaultLayoutOptionsClass -{ - gDefaultLayoutOptionsClass = defaultLayoutOptionsClass; -} - -+ (Class)defaultLayoutOptionsClass -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - if (gDefaultLayoutOptionsClass == nil) { - // If someone is asking for this and it hasn't been customized yet, use the default. - gDefaultLayoutOptionsClass = [ASLayoutOptions class]; - } - }); - return gDefaultLayoutOptionsClass; -} - -- (instancetype)init -{ - return nil; -} - -- (instancetype)initWithLayoutable:(id)layoutable -{ - self = [super init]; - if (self) { - - self.flexBasis = ASRelativeDimensionUnconstrained; - self.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMakeWithCGSize(CGSizeZero)); - self.layoutPosition = CGPointZero; - - // The following properties use a default value of 0 which we do not need to assign. - // self.spacingBefore = 0; - // self.spacingAfter = 0; - // self.flexGrow = NO; - // self.flexShrink = NO; - // self.alignSelf = ASStackLayoutAlignSelfAuto; - // self.ascender = 0; - // self.descender = 0; - - [self setValuesFromLayoutable:layoutable]; - } - return self; -} - -#pragma mark - NSCopying -- (id)copyWithZone:(NSZone *)zone -{ - ASLayoutOptions *copy = [[[self class] alloc] init]; - [copy copyFromOptions:self]; - return copy; -} - -- (void)copyFromOptions:(ASLayoutOptions *)layoutOptions -{ - ASDN::MutexLocker l(_propertyLock); - self.flexBasis = layoutOptions.flexBasis; - self.spacingAfter = layoutOptions.spacingAfter; - self.spacingBefore = layoutOptions.spacingBefore; - self.flexGrow = layoutOptions.flexGrow; - self.flexShrink = layoutOptions.flexShrink; - self.alignSelf = layoutOptions.alignSelf; - - self.ascender = layoutOptions.ascender; - self.descender = layoutOptions.descender; - - self.sizeRange = layoutOptions.sizeRange; - self.layoutPosition = layoutOptions.layoutPosition; -} - -/** - * Given an id, set up layout options that are intrinsically defined by the layoutable. - * - * While this could be done in the layoutable object itself, moving the logic into the ASLayoutOptions class - * allows a custom spec to set up defaults without needing to alter the layoutable itself. For example, - * image you were creating a custom baseline spec that needed ascender/descender. To assign values automatically - * when a text node's attribute string is set, you would need to subclass ASTextNode and assign the values in the - * override of setAttributeString. However, assigning the defaults in an ASLayoutOptions subclass's - * setValuesFromLayoutable allows you to create a custom spec without the need to create a - * subclass of ASTextNode. - * - * @param layoutable The layoutable object to inspect for default intrinsic layout option values - */ -- (void)setValuesFromLayoutable:(id)layoutable -{ - ASDN::MutexLocker l(_propertyLock); - if ([layoutable isKindOfClass:[ASDisplayNode class]]) { - ASDisplayNode *displayNode = (ASDisplayNode *)layoutable; - self.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(displayNode.preferredFrameSize), ASRelativeSizeMakeWithCGSize(displayNode.preferredFrameSize)); - - if ([layoutable isKindOfClass:[ASTextNode class]]) { - ASTextNode *textNode = (ASTextNode *)layoutable; - NSAttributedString *attributedString = textNode.attributedString; - if (attributedString.length > 0) { - CGFloat screenScale = ASScreenScale(); - self.ascender = round([[attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale; - self.descender = round([[attributedString attribute:NSFontAttributeName atIndex:attributedString.length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale; - } - } - - } -} - -- (CGFloat)spacingAfter -{ - ASDN::MutexLocker l(_propertyLock); - return _spacingAfter; -} - -- (void)setSpacingAfter:(CGFloat)spacingAfter -{ - ASDN::MutexLocker l(_propertyLock); - _spacingAfter = spacingAfter; -} - -- (CGFloat)spacingBefore -{ - ASDN::MutexLocker l(_propertyLock); - return _spacingBefore; -} - -- (void)setSpacingBefore:(CGFloat)spacingBefore -{ - ASDN::MutexLocker l(_propertyLock); - _spacingBefore = spacingBefore; -} - -- (BOOL)flexGrow -{ - ASDN::MutexLocker l(_propertyLock); - return _flexGrow; -} - -- (void)setFlexGrow:(BOOL)flexGrow -{ - ASDN::MutexLocker l(_propertyLock); - _flexGrow = flexGrow; -} - -- (BOOL)flexShrink -{ - ASDN::MutexLocker l(_propertyLock); - return _flexShrink; -} - -- (void)setFlexShrink:(BOOL)flexShrink -{ - ASDN::MutexLocker l(_propertyLock); - _flexShrink = flexShrink; -} - -- (ASRelativeDimension)flexBasis -{ - ASDN::MutexLocker l(_propertyLock); - return _flexBasis; -} - -- (void)setFlexBasis:(ASRelativeDimension)flexBasis -{ - ASDN::MutexLocker l(_propertyLock); - _flexBasis = flexBasis; -} - -- (ASStackLayoutAlignSelf)alignSelf -{ - ASDN::MutexLocker l(_propertyLock); - return _alignSelf; -} - -- (void)setAlignSelf:(ASStackLayoutAlignSelf)alignSelf -{ - ASDN::MutexLocker l(_propertyLock); - _alignSelf = alignSelf; -} - -- (CGFloat)ascender -{ - ASDN::MutexLocker l(_propertyLock); - return _ascender; -} - -- (void)setAscender:(CGFloat)ascender -{ - ASDN::MutexLocker l(_propertyLock); - _ascender = ascender; -} - -- (CGFloat)descender -{ - ASDN::MutexLocker l(_propertyLock); - return _descender; -} - -- (void)setDescender:(CGFloat)descender -{ - ASDN::MutexLocker l(_propertyLock); - _descender = descender; -} - -- (ASRelativeSizeRange)sizeRange -{ - ASDN::MutexLocker l(_propertyLock); - return _sizeRange; -} - -- (void)setSizeRange:(ASRelativeSizeRange)sizeRange -{ - ASDN::MutexLocker l(_propertyLock); - _sizeRange = sizeRange; -} - -- (CGPoint)layoutPosition -{ - ASDN::MutexLocker l(_propertyLock); - return _layoutPosition; -} - -- (void)setLayoutPosition:(CGPoint)layoutPosition -{ - ASDN::MutexLocker l(_propertyLock); - _layoutPosition = layoutPosition; -} - -@end diff --git a/AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.mm b/AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.mm deleted file mode 100644 index 334f42f1a5..0000000000 --- a/AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.mm +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ - -#import "ASLayoutOptionsPrivate.h" -#import - - -/** - * Both an ASDisplayNode and an ASLayoutSpec conform to ASLayoutable. There are several properties - * in ASLayoutable that are used as layoutOptions when a node or spec is used in a layout spec. - * These properties are provided for convenience, as they are forwards to the node or spec's - * ASLayoutOptions class. Instead of duplicating the property forwarding in both classes, we - * create a define that allows us to easily implement the forwards in one place. - * - * If you create a custom layout spec, we recommend this stragety if you decide to extend - * ASDisplayNode and ASLayoutSpec to provide convenience properties for any options that your - * layoutSpec may require. - */ -#define ASLayoutOptionsForwarding \ -- (ASLayoutOptions *)layoutOptions\ -{\ -ASDN::MutexLocker l(_layoutOptionsLock);\ -if (_layoutOptions == nil) {\ -_layoutOptions = [[[ASLayoutOptions defaultLayoutOptionsClass] alloc] initWithLayoutable:self];\ -}\ -return _layoutOptions;\ -}\ -\ -- (CGFloat)spacingBefore\ -{\ -return self.layoutOptions.spacingBefore;\ -}\ -\ -- (void)setSpacingBefore:(CGFloat)spacingBefore\ -{\ -self.layoutOptions.spacingBefore = spacingBefore;\ -}\ -\ -- (CGFloat)spacingAfter\ -{\ -return self.layoutOptions.spacingAfter;\ -}\ -\ -- (void)setSpacingAfter:(CGFloat)spacingAfter\ -{\ -self.layoutOptions.spacingAfter = spacingAfter;\ -}\ -\ -- (BOOL)flexGrow\ -{\ -return self.layoutOptions.flexGrow;\ -}\ -\ -- (void)setFlexGrow:(BOOL)flexGrow\ -{\ -self.layoutOptions.flexGrow = flexGrow;\ -}\ -\ -- (BOOL)flexShrink\ -{\ -return self.layoutOptions.flexShrink;\ -}\ -\ -- (void)setFlexShrink:(BOOL)flexShrink\ -{\ -self.layoutOptions.flexShrink = flexShrink;\ -}\ -\ -- (ASRelativeDimension)flexBasis\ -{\ -return self.layoutOptions.flexBasis;\ -}\ -\ -- (void)setFlexBasis:(ASRelativeDimension)flexBasis\ -{\ -self.layoutOptions.flexBasis = flexBasis;\ -}\ -\ -- (ASStackLayoutAlignSelf)alignSelf\ -{\ -return self.layoutOptions.alignSelf;\ -}\ -\ -- (void)setAlignSelf:(ASStackLayoutAlignSelf)alignSelf\ -{\ - self.layoutOptions.alignSelf = alignSelf;\ -}\ -\ -- (CGFloat)ascender\ -{\ - return self.layoutOptions.ascender;\ -}\ -\ -- (void)setAscender:(CGFloat)ascender\ -{\ - self.layoutOptions.ascender = ascender;\ -}\ -\ -- (CGFloat)descender\ -{\ - return self.layoutOptions.descender;\ -}\ -\ -- (void)setDescender:(CGFloat)descender\ -{\ - self.layoutOptions.descender = descender;\ -}\ -\ -- (ASRelativeSizeRange)sizeRange\ -{\ - return self.layoutOptions.sizeRange;\ -}\ -\ -- (void)setSizeRange:(ASRelativeSizeRange)sizeRange\ -{\ - self.layoutOptions.sizeRange = sizeRange;\ -}\ -\ -- (CGPoint)layoutPosition\ -{\ - return self.layoutOptions.layoutPosition;\ -}\ -\ -- (void)setLayoutPosition:(CGPoint)position\ -{\ - self.layoutOptions.layoutPosition = position;\ -}\ - - -@implementation ASDisplayNode(ASLayoutOptions) -ASLayoutOptionsForwarding -@end - -@implementation ASLayoutSpec(ASLayoutOptions) -ASLayoutOptionsForwarding -@end diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.h b/AsyncDisplayKit/Layout/ASLayoutSpec.h index 991c4224a7..dcb9b33246 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.h @@ -25,6 +25,8 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init; +@property (nullable, nonatomic, weak) id parent; + /** * Adds a child to this layout spec using a default identifier. * diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index abb428ebd1..c61e7a966f 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -8,29 +8,33 @@ * */ -#import "ASLayoutOptionsPrivate.h" +#import "ASLayoutSpec.h" #import "ASAssert.h" #import "ASBaseDefines.h" +#import "ASEnvironmentInternal.h" #import "ASInternalHelpers.h" #import "ASLayout.h" -#import "ASLayoutOptions.h" #import "ASThread.h" + #import static NSString * const kDefaultChildKey = @"kDefaultChildKey"; static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; -@interface ASLayoutSpec() +@interface ASLayoutSpec() { + ASEnvironmentState _environmentState; + ASDN::RecursiveMutex _propertyLock; +} @property (nonatomic, strong) NSMutableDictionary *layoutChildren; @end @implementation ASLayoutSpec // these dynamic properties all defined in ASLayoutOptionsPrivate.m -@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition, layoutOptions; +@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition; @synthesize layoutChildren = _layoutChildren; @synthesize isFinalLayoutable = _isFinalLayoutable; @@ -40,6 +44,8 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; return nil; } _isMutable = YES; + _environmentState = ASEnvironmentStateMakeDefault(); + return self; } @@ -75,7 +81,8 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; id finalLayoutable = [child finalLayoutable]; if (finalLayoutable != child) { - [finalLayoutable.layoutOptions copyFromOptions:child.layoutOptions]; + // Layout options state of child needs to be copied to final layoutable + finalLayoutable.environmentState.layoutOptionsState = child.environmentState.layoutOptionsState; return finalLayoutable; } } @@ -90,6 +97,15 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; return _layoutChildren; } +- (void)setParent:(id)parent +{ + _parent = parent; + + if ([parent supportsUpwardPropagation]) { + ASEnvironmentStatePropagateUp(parent, _environmentState.layoutOptionsState); + } +} + - (void)setChild:(id)child; { [self setChild:child forIdentifier:kDefaultChildKey]; @@ -98,7 +114,14 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; - (void)setChild:(id)child forIdentifier:(NSString *)identifier { ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); - self.layoutChildren[identifier] = [self layoutableToAddFromLayoutable:child];; + id finalLayoutable = [self layoutableToAddFromLayoutable:child]; + BOOL needsToPropagateLayoutOptionsState = (child != finalLayoutable); + self.layoutChildren[identifier] = finalLayoutable; + if (needsToPropagateLayoutOptionsState) { + // We only need to propagate up layout options in setChild: as up propagation is currently only supported for + // layout specification has with one child + [self propagateUpLayoutOptionsState]; + } } - (void)setChildren:(NSArray *)children @@ -128,6 +151,30 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; return self.layoutChildren[kDefaultChildrenKey]; } + +#pragma mark - ASEnvironment + +- (ASEnvironmentState)environmentState +{ + return _environmentState; +} + +- (void)setEnvironmentState:(ASEnvironmentState)environmentState +{ + _environmentState = environmentState; +} + +// Subclasses can override this method to return NO, because upward propagation is not enabled if a layout +// specification has more than one child. Currently ASStackLayoutSpec and ASStaticLayoutSpec are currently +// the specifications that are known to have more than one. +- (BOOL)supportsUpwardPropagation +{ + return YES; +} + +ASEnvironmentLayoutOptionsForwarding +ASEnvironmentLayoutExtensibilityForwarding + @end @implementation ASLayoutSpec (Debugging) diff --git a/AsyncDisplayKit/Layout/ASLayoutable.h b/AsyncDisplayKit/Layout/ASLayoutable.h index 121477b1f6..325a81535c 100644 --- a/AsyncDisplayKit/Layout/ASLayoutable.h +++ b/AsyncDisplayKit/Layout/ASLayoutable.h @@ -15,6 +15,8 @@ #import #import +#import +#import @class ASLayout; @class ASLayoutSpec; @@ -37,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN * access to the options via convenience properties. If you are creating custom layout spec, then you can * extend the backing layout options class to accommodate any new layout options. */ -@protocol ASLayoutable +@protocol ASLayoutable /** * @abstract Calculate a layout based on given size range. diff --git a/AsyncDisplayKit/Layout/ASLayoutable.mm b/AsyncDisplayKit/Layout/ASLayoutable.mm index 2af312c56e..23fd59e9ff 100644 --- a/AsyncDisplayKit/Layout/ASLayoutable.mm +++ b/AsyncDisplayKit/Layout/ASLayoutable.mm @@ -7,10 +7,21 @@ // #import "ASLayoutablePrivate.h" +#import "ASInternalHelpers.h" +#import "ASEnvironmentInternal.h" +#import "ASDisplayNodeInternal.h" +#import "ASTextNode.h" +#import "ASLayoutSpec.h" + #import "pthread.h" #import +#import +#import "ASThread.h" -ASLayoutableContext ASLayoutableContextMake(int32_t transitionID, BOOL needsVisualizeNode) +int32_t const ASLayoutableContextInvalidTransitionID = 0; +int32_t const ASLayoutableContextDefaultTransitionID = ASLayoutableContextInvalidTransitionID + 1; + +static inline ASLayoutableContext _ASLayoutableContextMake(int32_t transitionID, BOOL needsVisualizeNode) { struct ASLayoutableContext context; context.transitionID = transitionID; @@ -18,6 +29,26 @@ ASLayoutableContext ASLayoutableContextMake(int32_t transitionID, BOOL needsVisu return context; } +static inline BOOL _IsValidTransitionID(int32_t transitionID) +{ + return transitionID > ASLayoutableContextInvalidTransitionID; +} + +struct ASLayoutableContext const ASLayoutableContextNull = _ASLayoutableContextMake(ASLayoutableContextInvalidTransitionID, NO); + +BOOL ASLayoutableContextIsNull(struct ASLayoutableContext context) +{ + return !_IsValidTransitionID(context.transitionID); +} + +ASLayoutableContext ASLayoutableContextMake(int32_t transitionID, BOOL needsVisualizeNode) +{ + NSCAssert(_IsValidTransitionID(transitionID), @"Invalid transition ID"); + return _ASLayoutableContextMake(transitionID, needsVisualizeNode); +} + +// Note: This is a non-recursive static lock. If it needs to be recursive, use ASDISPLAYNODE_MUTEX_RECURSIVE_INITIALIZER +static ASDN::StaticMutex _layoutableContextLock = ASDISPLAYNODE_MUTEX_INITIALIZER; static std::map layoutableContextMap; static inline mach_port_t ASLayoutableGetCurrentContextKey() @@ -27,14 +58,26 @@ static inline mach_port_t ASLayoutableGetCurrentContextKey() void ASLayoutableSetCurrentContext(struct ASLayoutableContext context) { - layoutableContextMap[ASLayoutableGetCurrentContextKey()] = context; + const mach_port_t key = ASLayoutableGetCurrentContextKey(); + ASDN::StaticMutexLocker l(_layoutableContextLock); + layoutableContextMap[key] = context; } struct ASLayoutableContext ASLayoutableGetCurrentContext() { - return layoutableContextMap[ASLayoutableGetCurrentContextKey()]; + const mach_port_t key = ASLayoutableGetCurrentContextKey(); + ASDN::StaticMutexLocker l(_layoutableContextLock); + const auto it = layoutableContextMap.find(key); + if (it != layoutableContextMap.end()) { + // Found an interator with above key. "it->first" is the key itself, "it->second" is the context value. + return it->second; + } + return ASLayoutableContextNull; } -void ASLayoutableClearCurrentContext() { - layoutableContextMap.erase(ASLayoutableGetCurrentContextKey()); +void ASLayoutableClearCurrentContext() +{ + const mach_port_t key = ASLayoutableGetCurrentContextKey(); + ASDN::StaticMutexLocker l(_layoutableContextLock); + layoutableContextMap.erase(key); } diff --git a/AsyncDisplayKit/Layout/ASLayoutableExtensibility.h b/AsyncDisplayKit/Layout/ASLayoutableExtensibility.h new file mode 100644 index 0000000000..c35d04f046 --- /dev/null +++ b/AsyncDisplayKit/Layout/ASLayoutableExtensibility.h @@ -0,0 +1,25 @@ +// +// ASLayoutableExtensibility.h +// AsyncDisplayKit +// +// Created by Michael Schneider on 3/29/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +#import + +@protocol ASLayoutableExtensibility + +/// Currently up to 4 BOOL values +- (void)setLayoutOptionExtensionBool:(BOOL)value atIndex:(int)idx; +- (BOOL)layoutOptionExtensionBoolAtIndex:(int)idx; + +/// Currently up to 1 NSInteger value +- (void)setLayoutOptionExtensionInteger:(NSInteger)value atIndex:(int)idx; +- (NSInteger)layoutOptionExtensionIntegerAtIndex:(int)idx; + +/// Currently up to 1 UIEdgeInsets value +- (void)setLayoutOptionExtensionEdgeInsets:(UIEdgeInsets)value atIndex:(int)idx; +- (UIEdgeInsets)layoutOptionExtensionEdgeInsetsAtIndex:(int)idx; + +@end diff --git a/AsyncDisplayKit/Layout/ASLayoutablePrivate.h b/AsyncDisplayKit/Layout/ASLayoutablePrivate.h index 832bcf96c1..ce2de20f6d 100644 --- a/AsyncDisplayKit/Layout/ASLayoutablePrivate.h +++ b/AsyncDisplayKit/Layout/ASLayoutablePrivate.h @@ -11,7 +11,6 @@ #import @class ASLayoutSpec; -@class ASLayoutOptions; @protocol ASLayoutable; struct ASLayoutableContext { @@ -19,6 +18,14 @@ struct ASLayoutableContext { BOOL needsVisualizeNode; }; +extern int32_t const ASLayoutableContextInvalidTransitionID; + +extern int32_t const ASLayoutableContextDefaultTransitionID; + +extern struct ASLayoutableContext const ASLayoutableContextNull; + +extern BOOL ASLayoutableContextIsNull(struct ASLayoutableContext context); + extern struct ASLayoutableContext ASLayoutableContextMake(int32_t transitionID, BOOL needsVisualizeNode); extern void ASLayoutableSetCurrentContext(struct ASLayoutableContext context); @@ -52,9 +59,211 @@ extern void ASLayoutableClearCurrentContext(); */ @property (nonatomic, assign) BOOL isFinalLayoutable; +@end + + +#pragma mark - ASLayoutOptionsForwarding /** - * The class that holds all of the layoutOptions set on an ASLayoutable. + * Both an ASDisplayNode and an ASLayoutSpec conform to ASLayoutable. There are several properties + * in ASLayoutable that are used when a node or spec is used in a layout spec. + * These properties are provided for convenience, as they are forwards to the node or spec's + * properties. Instead of duplicating the property forwarding in both classes, we + * create a define that allows us to easily implement the forwards in one place. + * + * If you create a custom layout spec, we recommend this stragety if you decide to extend + * ASDisplayNode and ASLayoutSpec to provide convenience properties for any options that your + * layoutSpec may require. */ -@property (nonatomic, strong, readonly) ASLayoutOptions *layoutOptions; -@end + +#define ASEnvironmentLayoutOptionsForwarding \ +- (void)propagateUpLayoutOptionsState\ +{\ + id parent = [self parent];\ + if ([parent supportsUpwardPropagation]) {\ + ASEnvironmentStatePropagateUp(parent, _environmentState.layoutOptionsState);\ + }\ +}\ +\ +- (CGFloat)spacingAfter\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.spacingAfter;\ +}\ +\ +- (void)setSpacingAfter:(CGFloat)spacingAfter\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.spacingAfter = spacingAfter;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ +\ +- (CGFloat)spacingBefore\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.spacingBefore;\ +}\ +\ +- (void)setSpacingBefore:(CGFloat)spacingBefore\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.spacingBefore = spacingBefore;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ +\ +- (BOOL)flexGrow\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.flexGrow;\ +}\ +\ +- (void)setFlexGrow:(BOOL)flexGrow\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.flexGrow = flexGrow;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ +\ +- (BOOL)flexShrink\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.flexShrink;\ +}\ +\ +- (void)setFlexShrink:(BOOL)flexShrink\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.flexShrink = flexShrink;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ +\ +- (ASRelativeDimension)flexBasis\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.flexBasis;\ +}\ +\ +- (void)setFlexBasis:(ASRelativeDimension)flexBasis\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.flexBasis = flexBasis;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ +\ +- (ASStackLayoutAlignSelf)alignSelf\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.alignSelf;\ +}\ +\ +- (void)setAlignSelf:(ASStackLayoutAlignSelf)alignSelf\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.alignSelf = alignSelf;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ +\ +- (CGFloat)ascender\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.ascender;\ +}\ +\ +- (void)setAscender:(CGFloat)ascender\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.ascender = ascender;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ +\ +- (CGFloat)descender\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.descender;\ +}\ +\ +- (void)setDescender:(CGFloat)descender\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.descender = descender;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ +\ +- (ASRelativeSizeRange)sizeRange\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.sizeRange;\ +}\ +\ +- (void)setSizeRange:(ASRelativeSizeRange)sizeRange\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.sizeRange = sizeRange;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ +\ +- (CGPoint)layoutPosition\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _environmentState.layoutOptionsState.layoutPosition;\ +}\ +\ +- (void)setLayoutPosition:(CGPoint)layoutPosition\ +{\ + _propertyLock.lock();\ + _environmentState.layoutOptionsState.layoutPosition = layoutPosition;\ + [self propagateUpLayoutOptionsState];\ + _propertyLock.unlock();\ +}\ + + +#pragma mark - ASLayoutableExtensibility + +#define ASEnvironmentLayoutExtensibilityForwarding \ +- (void)setLayoutOptionExtensionBool:(BOOL)value atIndex:(int)idx\ +{\ + _propertyLock.lock();\ + _ASEnvironmentLayoutOptionsExtensionSetBoolAtIndex(self, idx, value);\ + _propertyLock.unlock();\ +}\ +\ +- (BOOL)layoutOptionExtensionBoolAtIndex:(int)idx\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _ASEnvironmentLayoutOptionsExtensionGetBoolAtIndex(self, idx);\ +}\ +\ +- (void)setLayoutOptionExtensionInteger:(NSInteger)value atIndex:(int)idx\ +{\ + _propertyLock.lock();\ + _ASEnvironmentLayoutOptionsExtensionSetIntegerAtIndex(self, idx, value);\ + _propertyLock.unlock();\ +}\ +\ +- (NSInteger)layoutOptionExtensionIntegerAtIndex:(int)idx\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _ASEnvironmentLayoutOptionsExtensionGetIntegerAtIndex(self, idx);\ +}\ +\ +- (void)setLayoutOptionExtensionEdgeInsets:(UIEdgeInsets)value atIndex:(int)idx\ +{\ + _propertyLock.lock();\ + _ASEnvironmentLayoutOptionsExtensionSetEdgeInsetsAtIndex(self, idx, value);\ + _propertyLock.unlock();\ +}\ +\ +- (UIEdgeInsets)layoutOptionExtensionEdgeInsetsAtIndex:(int)idx\ +{\ + ASDN::MutexLocker l(_propertyLock);\ + return _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(self, idx);\ +}\ diff --git a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm index 76539bf57a..26b6d449c7 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm @@ -198,6 +198,15 @@ @end +@implementation ASStackLayoutSpec (ASEnvironment) + +- (BOOL)supportsUpwardPropagation +{ + return NO; +} + +@end + @implementation ASStackLayoutSpec (Debugging) #pragma mark - ASLayoutableAsciiArtProtocol diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm index 2d0edba4cd..a727376a57 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm @@ -11,7 +11,6 @@ #import "ASStaticLayoutSpec.h" #import "ASLayoutSpecUtilities.h" -#import "ASLayoutOptions.h" #import "ASInternalHelpers.h" #import "ASLayout.h" @@ -86,6 +85,15 @@ @end +@implementation ASStaticLayoutSpec (ASEnvironment) + +- (BOOL)supportsUpwardPropagation +{ + return NO; +} + +@end + @implementation ASStaticLayoutSpec (Debugging) #pragma mark - ASLayoutableAsciiArtProtocol diff --git a/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h b/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h index 996ec2a7d0..07cb3440b8 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h +++ b/AsyncDisplayKit/Private/ASDisplayNode+FrameworkPrivate.h @@ -16,7 +16,6 @@ #import "ASDisplayNode.h" #import "ASSentinel.h" #import "ASThread.h" -#import "ASLayoutOptions.h" #import "_ASDisplayLayer.h" NS_ASSUME_NONNULL_BEGIN diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index bd00cd9417..e8930b9865 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -16,9 +16,9 @@ #import "ASDisplayNode.h" #import "ASSentinel.h" #import "ASThread.h" -#import "ASLayoutOptions.h" #import "_ASTransitionContext.h" #import "ASDisplayNodeLayoutContext.h" +#import "ASEnvironment.h" #include @@ -97,6 +97,7 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo // This is the desired contentsScale, not the scale at which the layer's contents should be displayed CGFloat _contentsScaleForDisplay; + ASEnvironmentState _environmentState; ASLayout *_layout; ASSizeRange _constrainedSize; diff --git a/AsyncDisplayKit/Private/ASEnvironmentInternal.h b/AsyncDisplayKit/Private/ASEnvironmentInternal.h new file mode 100644 index 0000000000..9cf9a11e55 --- /dev/null +++ b/AsyncDisplayKit/Private/ASEnvironmentInternal.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import "ASEnvironment.h" + +#pragma once + +enum class ASEnvironmentStatePropagation { DOWN, UP }; + + +#pragma mark - Set and get extensible values for layout options + +void _ASEnvironmentLayoutOptionsExtensionSetBoolAtIndex(id object, int idx, BOOL value); +BOOL _ASEnvironmentLayoutOptionsExtensionGetBoolAtIndex(id object, int idx); + +void _ASEnvironmentLayoutOptionsExtensionSetIntegerAtIndex(id object, int idx, NSInteger value); +NSInteger _ASEnvironmentLayoutOptionsExtensionGetIntegerAtIndex(id object, int idx); + +void _ASEnvironmentLayoutOptionsExtensionSetEdgeInsetsAtIndex(id object, int idx, UIEdgeInsets value); +UIEdgeInsets _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(id object, int idx); + + +#pragma mark - Traversing an ASEnvironment Tree + +void ASEnvironmentPerformBlockOnObjectAndChildren(id object, void(^block)(id object)); +void ASEnvironmentPerformBlockOnObjectAndParents(id object, void(^block)(id object)); + + +#pragma mark - Merging + +static const struct ASEnvironmentLayoutOptionsState ASEnvironmentDefaultLayoutOptionsState = {}; +ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState state, ASEnvironmentStatePropagation propagation); + + +static const struct ASEnvironmentHierarchyState ASEnvironmentDefaultHierarchyState = {}; +ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState state, ASEnvironmentStatePropagation propagation); + + +#pragma mark - Propagation + +template +void ASEnvironmentStatePropagateDown(id object, ASEnvironmentStateType state) { + ASEnvironmentPerformBlockOnObjectAndChildren(object, ^(id node) { + object.environmentState = ASEnvironmentMergeObjectAndState(object.environmentState, state, ASEnvironmentStatePropagation::DOWN); + }); +} + +template +void ASEnvironmentStatePropagateUp(id object, ASEnvironmentStateType state) { + ASEnvironmentPerformBlockOnObjectAndParents(object, ^(id node) { + object.environmentState = ASEnvironmentMergeObjectAndState(object.environmentState, state, ASEnvironmentStatePropagation::UP); + }); +} + +template +void ASEnvironmentStateApply(id object, ASEnvironmentStateType& state, ASEnvironmentStatePropagation propagate) { + if (propagate == ASEnvironmentStatePropagation::DOWN) { + ASEnvironmentStatePropagateUp(object, state); + } else if (propagate == ASEnvironmentStatePropagation::UP) { + ASEnvironmentStatePropagateDown(object, state); + } +} diff --git a/AsyncDisplayKit/Private/ASEnvironmentInternal.mm b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm new file mode 100644 index 0000000000..4bec0df268 --- /dev/null +++ b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2014-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import "ASEnvironmentInternal.h" + +#import + +//#define LOG(...) NSLog(__VA_ARGS__) +#define LOG(...) + +#pragma mark - Traversing an ASEnvironment Tree + +void ASEnvironmentPerformBlockOnObjectAndChildren(id object, void(^block)(id node)) +{ + if (!object) { + return; + } + + std::queue> queue; + queue.push(object); + + while (!queue.empty()) { + id object = queue.front(); queue.pop(); + + block(object); + + for (id child in [object children]) { + queue.push(child); + } + } +} + +void ASEnvironmentPerformBlockOnObjectAndParents(id object, void(^block)(id node)) +{ + while (object) { + block(object); + object = [object parent]; + } +} + + +#pragma mark - Set and get extensible values from state structs + +void _ASEnvironmentLayoutOptionsExtensionSetBoolAtIndex(id object, int idx, BOOL value) +{ + NSCAssert(idx < kMaxEnvironmentStateBoolExtensions, @"Setting index outside of max bool extensions space"); + + ASEnvironmentStateExtensions extension = object.environmentState.layoutOptionsState._extensions; + extension.boolExtensions[idx] = value; + object.environmentState.layoutOptionsState._extensions = extension; +} + +BOOL _ASEnvironmentLayoutOptionsExtensionGetBoolAtIndex(id object, int idx) +{ + NSCAssert(idx < kMaxEnvironmentStateBoolExtensions, @"Accessing index outside of max bool extensions space"); + return object.environmentState.layoutOptionsState._extensions.boolExtensions[idx]; +} + +void _ASEnvironmentLayoutOptionsExtensionSetIntegerAtIndex(id object, int idx, NSInteger value) +{ + NSCAssert(idx < kMaxEnvironmentStateIntegerExtensions, @"Setting index outside of max integer extensions space"); + + ASEnvironmentStateExtensions extension = object.environmentState.layoutOptionsState._extensions; + extension.integerExtensions[idx] = value; + object.environmentState.layoutOptionsState._extensions = extension; +} + +NSInteger _ASEnvironmentLayoutOptionsExtensionGetIntegerAtIndex(id object, int idx) +{ + NSCAssert(idx < kMaxEnvironmentStateIntegerExtensions, @"Accessing index outside of max integer extensions space"); + return object.environmentState.layoutOptionsState._extensions.integerExtensions[idx]; +} + +void _ASEnvironmentLayoutOptionsExtensionSetEdgeInsetsAtIndex(id object, int idx, UIEdgeInsets value) +{ + NSCAssert(idx < kMaxEnvironmentStateEdgeInsetExtensions, @"Setting index outside of max edge insets extensions space"); + + ASEnvironmentStateExtensions extension = object.environmentState.layoutOptionsState._extensions; + extension.edgeInsetsExtensions[idx] = value; + object.environmentState.layoutOptionsState._extensions = extension; +} + +UIEdgeInsets _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(id object, int idx) +{ + NSCAssert(idx < kMaxEnvironmentStateEdgeInsetExtensions, @"Accessing index outside of max edge insets extensions space"); + return object.environmentState.layoutOptionsState._extensions.edgeInsetsExtensions[idx]; +} + + +#pragma mark - Merging functions for states + +ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState state, ASEnvironmentStatePropagation propagation) { + // Merge object and hierarchy state + LOG(@"Merge object and state: %@ - ASEnvironmentHierarchyState", object); + return environmentState; +} + +ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState state, ASEnvironmentStatePropagation propagation) { + // Merge object and layout options state + LOG(@"Merge object and state: %@ - ASEnvironmentLayoutOptionsState", object); + + // Support propagate up + if (propagation == ASEnvironmentStatePropagation::UP) { + + // Object is the parent and the state is the state of the child + const ASEnvironmentLayoutOptionsState defaultState = ASEnvironmentDefaultLayoutOptionsState; + ASEnvironmentLayoutOptionsState parentState = environmentState.layoutOptionsState; + + // For every field check if the parent value is equal to the default than propegate up the child value to + // the parent + if (parentState.spacingBefore != defaultState.spacingBefore) { + parentState.spacingBefore = state.spacingBefore; + } + if (parentState.spacingAfter != defaultState.spacingAfter) { + parentState.spacingAfter = state.spacingAfter; + } + if (parentState.alignSelf != defaultState.alignSelf) { + parentState.alignSelf = defaultState.alignSelf; + } + if (parentState.flexGrow != defaultState.flexGrow) { + parentState.flexGrow = defaultState.flexGrow; + } + if (!ASRelativeDimensionEqualToRelativeDimension(parentState.flexBasis, defaultState.flexBasis)) { + parentState.flexBasis = defaultState.flexBasis; + } + if (parentState.alignSelf != defaultState.alignSelf) { + parentState.alignSelf = defaultState.alignSelf; + } + if (parentState.ascender != defaultState.ascender) { + parentState.ascender = defaultState.ascender; + } + + if (!ASRelativeSizeRangeEqualToRelativeSizeRange(parentState.sizeRange, defaultState.sizeRange)) { + parentState.sizeRange = defaultState.sizeRange; + } + if (CGPointEqualToPoint(parentState.layoutPosition, defaultState.layoutPosition)) { + parentState.layoutPosition = defaultState.layoutPosition; + } + + environmentState.layoutOptionsState = parentState; + } + + return environmentState; +} diff --git a/AsyncDisplayKit/Private/ASLayoutOptionsPrivate.h b/AsyncDisplayKit/Private/ASLayoutOptionsPrivate.h deleted file mode 100644 index 34a26da4f2..0000000000 --- a/AsyncDisplayKit/Private/ASLayoutOptionsPrivate.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ - -#import -#import -#import - -@interface ASDisplayNode(ASLayoutOptions) -@end - -@interface ASDisplayNode() -{ - ASLayoutOptions *_layoutOptions; - ASDN::RecursiveMutex _layoutOptionsLock; -} -@end - -@interface ASLayoutSpec(ASLayoutOptions) -@end - -@interface ASLayoutSpec() -{ - ASLayoutOptions *_layoutOptions; - ASDN::RecursiveMutex _layoutOptionsLock; -} -@end diff --git a/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm b/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm index ed6b622162..46df924adf 100644 --- a/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm @@ -12,7 +12,6 @@ #import "ASLayoutSpecUtilities.h" #import "ASStackLayoutSpecUtilities.h" -#import "ASLayoutOptions.h" static CGFloat baselineForItem(const ASStackLayoutSpecStyle &style, const ASLayout *layout) { diff --git a/AsyncDisplayKit/Private/ASStackPositionedLayout.mm b/AsyncDisplayKit/Private/ASStackPositionedLayout.mm index 428319d317..cd18dd2157 100644 --- a/AsyncDisplayKit/Private/ASStackPositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackPositionedLayout.mm @@ -14,7 +14,6 @@ #import "ASLayoutSpecUtilities.h" #import "ASStackLayoutSpecUtilities.h" #import "ASLayoutable.h" -#import "ASLayoutOptions.h" #import "ASAssert.h" static CGFloat crossOffset(const ASStackLayoutSpecStyle &style, diff --git a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm index a19ae298ba..57902a6b4e 100644 --- a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm @@ -14,7 +14,6 @@ #import "ASLayoutSpecUtilities.h" #import "ASStackLayoutSpecUtilities.h" -#import "ASLayoutOptions.h" /** Sizes the child given the parameters specified, and returns the computed layout. @@ -116,8 +115,7 @@ static CGFloat computeStackDimensionSum(const std::vector child = l.child; - const ASLayoutOptions *layoutOptions = child.layoutOptions; - return x + layoutOptions.spacingBefore + layoutOptions.spacingAfter; + return x + child.spacingBefore + child.spacingAfter; }); // Sum up the childrens' dimensions (including spacing) in the stack direction. diff --git a/AsyncDisplayKit/TextKit/ASTextKitHelpers.h b/AsyncDisplayKit/TextKit/ASTextKitComponents.h similarity index 66% rename from AsyncDisplayKit/TextKit/ASTextKitHelpers.h rename to AsyncDisplayKit/TextKit/ASTextKitComponents.h index c66b019f96..17f6c1f9cc 100644 --- a/AsyncDisplayKit/TextKit/ASTextKitHelpers.h +++ b/AsyncDisplayKit/TextKit/ASTextKitComponents.h @@ -6,11 +6,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import - -#import #import -#import "ASBaseDefines.h" +#import NS_ASSUME_NONNULL_BEGIN @@ -37,8 +34,20 @@ ASDISPLAYNODE_INLINE CGSize ceilSizeValue(CGSize s) @return An `ASTextKitComponents` containing the created components. The text view component will be nil. @discussion The returned components will be hooked up together, so they are ready for use as a system upon return. */ -+ (ASTextKitComponents *)componentsWithAttributedSeedString:(nullable NSAttributedString *)attributedSeedString - textContainerSize:(CGSize)textContainerSize; ++ (instancetype)componentsWithAttributedSeedString:(nullable NSAttributedString *)attributedSeedString + textContainerSize:(CGSize)textContainerSize; + +/** + @abstract Creates the stack of TextKit components. + @param textStorage The NSTextStorage to use. + @param textContainerSize The size of the text-container. Typically, size specifies the constraining width of the layout, and FLT_MAX for height. Pass CGSizeZero if these components will be hooked up to a UITextView, which will manage the text container's size itself. + @param layoutManager The NSLayoutManager to use. + @return An `ASTextKitComponents` containing the created components. The text view component will be nil. + @discussion The returned components will be hooked up together, so they are ready for use as a system upon return. + */ ++ (instancetype)componentsWithTextStorage:(NSTextStorage *)textStorage + textContainerSize:(CGSize)textContainerSize + layoutManager:(NSLayoutManager *)layoutManager; /** @abstract Returns the bounding size for the text view's text. diff --git a/AsyncDisplayKit/TextKit/ASTextKitHelpers.mm b/AsyncDisplayKit/TextKit/ASTextKitComponents.m similarity index 67% rename from AsyncDisplayKit/TextKit/ASTextKitHelpers.mm rename to AsyncDisplayKit/TextKit/ASTextKitComponents.m index 82252b1b7f..4283e3993f 100644 --- a/AsyncDisplayKit/TextKit/ASTextKitHelpers.mm +++ b/AsyncDisplayKit/TextKit/ASTextKitComponents.m @@ -6,7 +6,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "ASTextKitHelpers.h" +#import "ASTextKitComponents.h" @interface ASTextKitComponents () @@ -19,15 +19,25 @@ @implementation ASTextKitComponents -+ (ASTextKitComponents *)componentsWithAttributedSeedString:(NSAttributedString *)attributedSeedString - textContainerSize:(CGSize)textContainerSize ++ (instancetype)componentsWithAttributedSeedString:(NSAttributedString *)attributedSeedString + textContainerSize:(CGSize)textContainerSize { - ASTextKitComponents *components = [[ASTextKitComponents alloc] init]; + NSTextStorage *textStorage = attributedSeedString ? [[NSTextStorage alloc] initWithAttributedString:attributedSeedString] : [[NSTextStorage alloc] init]; - // Create the TextKit component stack with our default configuration. - components.textStorage = (attributedSeedString ? [[NSTextStorage alloc] initWithAttributedString:attributedSeedString] : [[NSTextStorage alloc] init]); + return [self componentsWithTextStorage:textStorage + textContainerSize:textContainerSize + layoutManager:[[NSLayoutManager alloc] init]]; +} - components.layoutManager = [[NSLayoutManager alloc] init]; ++ (instancetype)componentsWithTextStorage:(NSTextStorage *)textStorage + textContainerSize:(CGSize)textContainerSize + layoutManager:(NSLayoutManager *)layoutManager +{ + ASTextKitComponents *components = [[self alloc] init]; + + components.textStorage = textStorage; + + components.layoutManager = layoutManager; [components.textStorage addLayoutManager:components.layoutManager]; components.textContainer = [[NSTextContainer alloc] initWithSize:textContainerSize]; diff --git a/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm index f6ba9da1e5..bb38be0d18 100644 --- a/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm @@ -13,7 +13,6 @@ #import "ASBackgroundLayoutSpec.h" #import "ASCenterLayoutSpec.h" #import "ASStackLayoutSpec.h" -#import "ASLayoutOptions.h" static const ASSizeRange kSize = {{100, 120}, {320, 160}}; diff --git a/AsyncDisplayKitTests/ASRelativeLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASRelativeLayoutSpecSnapshotTests.mm index 468b515a05..213045ea68 100644 --- a/AsyncDisplayKitTests/ASRelativeLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASRelativeLayoutSpecSnapshotTests.mm @@ -13,7 +13,6 @@ #import "ASBackgroundLayoutSpec.h" #import "ASRelativeLayoutSpec.h" #import "ASStackLayoutSpec.h" -#import "ASLayoutOptions.h" static const ASSizeRange kSize = {{100, 120}, {320, 160}}; diff --git a/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm index 20989a71d3..d5ca9074aa 100644 --- a/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm @@ -15,7 +15,6 @@ #import "ASBackgroundLayoutSpec.h" #import "ASRatioLayoutSpec.h" #import "ASInsetLayoutSpec.h" -#import "ASLayoutOptions.h" @interface ASStackLayoutSpecSnapshotTests : ASLayoutSpecSnapshotTestCase @end diff --git a/AsyncDisplayKitTests/ASTextNodeWordKernerTests.mm b/AsyncDisplayKitTests/ASTextNodeWordKernerTests.mm index 6085a88b79..2aba8a3748 100644 --- a/AsyncDisplayKitTests/ASTextNodeWordKernerTests.mm +++ b/AsyncDisplayKitTests/ASTextNodeWordKernerTests.mm @@ -8,7 +8,7 @@ #import -#import "ASTextKitHelpers.h" +#import "ASTextKitComponents.h" #import "ASTextNodeTypes.h" #import "ASTextNodeWordKerner.h" diff --git a/README.md b/README.md index 68c98c516b..82be85be80 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,9 @@ [![Coverage Status](https://coveralls.io/repos/facebook/AsyncDisplayKit/badge.svg?branch=master)](https://coveralls.io/r/facebook/AsyncDisplayKit?branch=master) [![Version](https://img.shields.io/cocoapods/v/AsyncDisplayKit.svg)](http://cocoapods.org/pods/AsyncDisplayKit) [![Platform](https://img.shields.io/cocoapods/p/AsyncDisplayKit.svg)]() +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![License](https://img.shields.io/cocoapods/l/AsyncDisplayKit.svg)](https://github.com/facebook/AsyncDisplayKit/blob/master/LICENSE) -[![Downloads](https://img.shields.io/badge/downloads-%3E120k-green.svg)](http://cocoapods.org/pods/AsyncDisplayKit) +[![Downloads](https://img.shields.io/badge/downloads-%3E320k-green.svg)](http://cocoapods.org/pods/AsyncDisplayKit) AsyncDisplayKit is an iOS framework that keeps even the most complex user interfaces smooth and responsive. It was originally built to make Facebook's diff --git a/build.sh b/build.sh index 0d7fa4cd70..c3744eab05 100755 --- a/build.sh +++ b/build.sh @@ -1,8 +1,8 @@ #!/bin/bash # **** Update me when new Xcode versions are released! **** -PLATFORM="platform=iOS Simulator,OS=9.2,name=iPhone 6" -SDK="iphonesimulator9.2" +PLATFORM="platform=iOS Simulator,OS=9.3,name=iPhone 6" +SDK="iphonesimulator9.3" # It is pitch black. diff --git a/examples/EditableText/CustomCollectionView.gif b/examples/EditableText/CustomCollectionView.gif new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/README.md b/examples/README.md index 358c9162ff..87c32c6375 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,6 +5,178 @@ Run `pod install` in each sample project directory to set up their dependencies. +## Example Catalog + +### ASCollectionView [ObjC] + +![ASCollectionView Example App Screenshot](./Screenshots/ASCollectionView.png?raw=true) + +Featuring: +- ASCollectionView with header/footer supplementary node support +- ASCollectionView batch API +- ASDelegateProxy + +### ASTableViewStressTest [ObjC] + +![ASTableViewStressTest Example App Screenshot](./Screenshots/ASTableViewStressTest.png?raw=true) + +### ASViewController [ObjC] + +![ASViewController Example App Screenshot](./Screenshots/ASViewController.png?raw=true) + +Featuring: +- ASViewController +- ASTableView +- ASMultiplexImageNode +- ASLayoutSpec + +### BackgroundPropertySetting [Swift] + +![BackgroundPropertySetting Example App gif](./Screenshots/BackgroundPropertySetting.gif?raw=true) + +Featuring: +- ASDK Swift compatibility +- ASViewController +- ASCollectionView +- thread affinity +- ASLayoutSpec + +### CarthageBuildTest +### CatDealsCollectionView [ObjC] + +![CatDealsCollectionView Example App Screenshot](./Screenshots/CatDealsCollectionView.png?raw=true) + +Featuring: +- ASCollectionView +- ASRangeTuningParameters +- Placeholder Images +- ASLayoutSpec + +### CollectionViewWithViewControllerCells [ObjC] + +![CollectionViewWithViewControllerCells Example App Screenshot](./Screenshots/CollectionViewWithViewControllerCells.png?raw=true) + +Featuring: +- custom collection view layout +- ASLayoutSpec +- ASMultiplexImageNode + +### CustomCollectionView [ObjC] + +![CustomCollectionView Example App gif](./Screenshots/CustomCollectionView.gif?raw=true) + +Featuring: +- custom collection view layout +- ASCollectionView with sections + +### EditableText [ObjC] + +![EditableText Example App Screenshot](./Screenshots/EditableText.png?raw=true) + +Featuring: +- ASEditableTextNode + +### HorizontalwithinVerticalScrolling [ObjC] + +![HorizontalwithinVerticalScrolling Example App gif](./Screenshots/HorizontalwithinVerticalScrolling.gif?raw=true) + +Featuring: +- UIViewController with ASTableView +- ASCollectionView +- ASCellNode + +### Kittens [ObjC] + +![Kittens Example App Screenshot](./Screenshots/Kittens.png?raw=true) + +Featuring: +- UIViewController with ASTableView +- ASCellNodes with ASNetworkImageNode and ASTextNode + +### Multiplex [ObjC] + +![Multiplex Example App gif](./Screenshots/Multiplex.gif?raw=true) + +Featuring: +- ASMultiplexImageNode (with artificial delay inserted) +- ASLayoutSpec + +### PagerNode [ObjC] + +Featuring: +- ASPagerNode + +### Placeholders [ObjC] + +Featuring: +- ASDisplayNodes now have an overidable method -placeholderImage that lets you provide a custom UIImage to display while a node is displaying asyncronously. The default implementation of this method returns nil and thus does nothing. A provided example project also demonstrates using the placeholder API. + +### SocialAppLayout [ObjC] + +![SocialAppLayout Example App Screenshot](./Screenshots/SocialAppLayout.png?raw=true) + +Featuring: +- ASLayoutSpec +- UIViewController with ASTableView + +### Swift [Swift] + +![Swift Example App Screenshot](./Screenshots/Swift.png?raw=true) + +Featuring: +- ASViewController with ASTableNode + +### SynchronousConcurrency [ObjC] + +![SynchronousConcurrency Example App Screenshot](./Screenshots/SynchronousConcurrency.png?raw=true) + +Implementation of Synchronous Concurrency features for AsyncDisplayKit 2.0 + +This provides internal features on _ASAsyncTransaction and ASDisplayNode to facilitate +implementing public API that allows clients to choose if they would prefer to block +on the completion of unfinished rendering, rather than allow a placeholder state to +become visible. + +The internal features are: +-[_ASAsyncTransaction waitUntilComplete] +-[ASDisplayNode recursivelyEnsureDisplay] + +Also provided are two such implementations: +-[ASCellNode setNeverShowPlaceholders:], which integrates with both Tables and Collections +-[ASViewController setNeverShowPlaceholders:], which should work with Nav and Tab controllers. + +Lastly, on ASDisplayNode, a new property .shouldBypassEnsureDisplay allows individual node types +to exempt themselves from blocking the main thread on their display. + +By implementing the feature at the ASCellNode level rather than ASTableView & ASCollectionView, +developers can retain fine-grained control on display characteristics. For example, certain +cell types may be appropriate to display to the user with placeholders, whereas others may not. + +### SynchronousKittens [ObjC] + +### VerticalWithinHorizontalScrolling [ObjC] + +![VerticalWithinHorizontalScrolling Example App Screenshot](./Screenshots/VerticalWithinHorizontalScrolling.png?raw=true) + +Features: +- UIViewController containing ASPagerNode containing ASTableNodes + +### Videos [ObjC] + +![VideoTableView Example App gif](./Screenshots/Videos.gif?raw=true) + +Featuring: +- ASVideoNode + +### VideoTableView [ObjC] + +![VideoTableView Example App Screenshot](./Screenshots/VideoTableView.png?raw=true) + +Featuring: +- ASVideoNode +- ASTableView +- ASCellNode + ## License This file provided by Facebook is for non-commercial testing and evaluation diff --git a/examples/Screenshots/ASCollectionView.png b/examples/Screenshots/ASCollectionView.png new file mode 100644 index 0000000000..3aaff368e5 Binary files /dev/null and b/examples/Screenshots/ASCollectionView.png differ diff --git a/examples/Screenshots/ASTableViewStressTest.png b/examples/Screenshots/ASTableViewStressTest.png new file mode 100644 index 0000000000..cd7aae2d9d Binary files /dev/null and b/examples/Screenshots/ASTableViewStressTest.png differ diff --git a/examples/Screenshots/ASViewController.png b/examples/Screenshots/ASViewController.png new file mode 100644 index 0000000000..545f3c8d63 Binary files /dev/null and b/examples/Screenshots/ASViewController.png differ diff --git a/examples/Screenshots/BackgroundPropertySetting.gif b/examples/Screenshots/BackgroundPropertySetting.gif new file mode 100644 index 0000000000..e2655ef235 Binary files /dev/null and b/examples/Screenshots/BackgroundPropertySetting.gif differ diff --git a/examples/Screenshots/CatDealsCollectionView.png b/examples/Screenshots/CatDealsCollectionView.png new file mode 100644 index 0000000000..72f9179e94 Binary files /dev/null and b/examples/Screenshots/CatDealsCollectionView.png differ diff --git a/examples/Screenshots/CollectionViewWithViewControllerCells.png b/examples/Screenshots/CollectionViewWithViewControllerCells.png new file mode 100644 index 0000000000..078b7b945f Binary files /dev/null and b/examples/Screenshots/CollectionViewWithViewControllerCells.png differ diff --git a/examples/Screenshots/CustomCollectionView.gif b/examples/Screenshots/CustomCollectionView.gif new file mode 100644 index 0000000000..8d8a2aed1e Binary files /dev/null and b/examples/Screenshots/CustomCollectionView.gif differ diff --git a/examples/Screenshots/EditableText.png b/examples/Screenshots/EditableText.png new file mode 100644 index 0000000000..1aa8d6db9b Binary files /dev/null and b/examples/Screenshots/EditableText.png differ diff --git a/examples/Screenshots/HorizontalwithinVerticalScrolling.gif b/examples/Screenshots/HorizontalwithinVerticalScrolling.gif new file mode 100644 index 0000000000..fe722a308d Binary files /dev/null and b/examples/Screenshots/HorizontalwithinVerticalScrolling.gif differ diff --git a/examples/Screenshots/Kittens.png b/examples/Screenshots/Kittens.png new file mode 100644 index 0000000000..91d9bf36fa Binary files /dev/null and b/examples/Screenshots/Kittens.png differ diff --git a/examples/Screenshots/Multiplex.gif b/examples/Screenshots/Multiplex.gif new file mode 100644 index 0000000000..fcb98cad62 Binary files /dev/null and b/examples/Screenshots/Multiplex.gif differ diff --git a/examples/Screenshots/SocialAppLayout.png b/examples/Screenshots/SocialAppLayout.png new file mode 100644 index 0000000000..33d6672102 Binary files /dev/null and b/examples/Screenshots/SocialAppLayout.png differ diff --git a/examples/Screenshots/Swift.png b/examples/Screenshots/Swift.png new file mode 100644 index 0000000000..b099a17229 Binary files /dev/null and b/examples/Screenshots/Swift.png differ diff --git a/examples/Screenshots/SynchronousConcurrency.png b/examples/Screenshots/SynchronousConcurrency.png new file mode 100644 index 0000000000..e0eac3788e Binary files /dev/null and b/examples/Screenshots/SynchronousConcurrency.png differ diff --git a/examples/Screenshots/VerticalWithinHorizontalScrolling.gif b/examples/Screenshots/VerticalWithinHorizontalScrolling.gif new file mode 100644 index 0000000000..c50474b19b Binary files /dev/null and b/examples/Screenshots/VerticalWithinHorizontalScrolling.gif differ diff --git a/examples/Screenshots/VideoTableView.png b/examples/Screenshots/VideoTableView.png new file mode 100644 index 0000000000..ddeefdc773 Binary files /dev/null and b/examples/Screenshots/VideoTableView.png differ diff --git a/examples/Screenshots/Videos.gif b/examples/Screenshots/Videos.gif new file mode 100644 index 0000000000..5e5c5f2ca9 Binary files /dev/null and b/examples/Screenshots/Videos.gif differ