mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-17 11:50:56 +00:00
Merge remote-tracking branch 'facebook/master'
This commit is contained in:
commit
ae29cd2721
@ -190,7 +190,6 @@
|
||||
25E327581C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; };
|
||||
25E327591C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; };
|
||||
2767E9411BB19BD600EA9B77 /* ASViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2767E9421BB19BD600EA9B77 /* ASViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */; };
|
||||
2911485C1A77147A005D0878 /* ASControlNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2911485B1A77147A005D0878 /* ASControlNodeTests.m */; };
|
||||
291B63FB1AA53A7A000A71B3 /* ASScrollDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 296A0A311A951715005ACEAA /* ASScrollDirection.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
292C599F1A956527007E5DD6 /* ASLayoutRangeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C59991A956527007E5DD6 /* ASLayoutRangeType.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -251,6 +250,7 @@
|
||||
509E68661B3AEDD7009B9150 /* CGRect+ASConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E201B376416007741D0 /* CGRect+ASConvenience.m */; };
|
||||
636EA1A41C7FF4EC00EE152F /* NSArray+Diffing.m in Sources */ = {isa = PBXBuildFile; fileRef = DBC452DA1C5BF64600B16017 /* NSArray+Diffing.m */; };
|
||||
636EA1A51C7FF4EF00EE152F /* ASDefaultPlayButton.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */; };
|
||||
680346941CE4052A0009FEB4 /* ASNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85DC1CE29AB700EDD713 /* ASNavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68355B311CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */; };
|
||||
68355B341CB579B9001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */; };
|
||||
68355B3A1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */; };
|
||||
@ -273,10 +273,19 @@
|
||||
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 */; };
|
||||
68FC85DE1CE29AB700EDD713 /* ASNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85DC1CE29AB700EDD713 /* ASNavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68FC85DF1CE29AB700EDD713 /* ASNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85DD1CE29AB700EDD713 /* ASNavigationController.m */; };
|
||||
68FC85E21CE29B7E00EDD713 /* ASTabBarController.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85E01CE29B7E00EDD713 /* ASTabBarController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68FC85E31CE29B7E00EDD713 /* ASTabBarController.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85E01CE29B7E00EDD713 /* ASTabBarController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68FC85E41CE29B7E00EDD713 /* ASTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */; };
|
||||
68FC85E51CE29B7E00EDD713 /* ASTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */; };
|
||||
68FC85E61CE29B9400EDD713 /* ASNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85DD1CE29AB700EDD713 /* ASNavigationController.m */; };
|
||||
68FC85E91CE29C7D00EDD713 /* ASVisibilityProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68FC85EA1CE29C7D00EDD713 /* ASVisibilityProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68FC85EB1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */; };
|
||||
68FC85EC1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */; };
|
||||
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, ); }; };
|
||||
69CB62AB1CB8165900024920 /* _ASDisplayViewAccessiblity.h in Headers */ = {isa = PBXBuildFile; fileRef = 69CB62A91CB8165900024920 /* _ASDisplayViewAccessiblity.h */; };
|
||||
@ -327,6 +336,18 @@
|
||||
9C55866C1BD54A3000B50E3A /* ASAsciiArtBoxCreator.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5586671BD549CB00B50E3A /* ASAsciiArtBoxCreator.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
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, ); }; };
|
||||
9C70F2031CDA4EFA007D6C76 /* ASTraitCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9C70F2041CDA4EFA007D6C76 /* ASTraitCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */; };
|
||||
9C70F2051CDA4F06007D6C76 /* ASTraitCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */; };
|
||||
9C70F2061CDA4F0C007D6C76 /* ASTraitCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9C70F2081CDAA3C6007D6C76 /* ASEnvironment.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */; };
|
||||
9C70F2091CDABA36007D6C76 /* ASViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */; };
|
||||
9C70F20A1CDBE949007D6C76 /* ASTableNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */; };
|
||||
9C70F20B1CDBE9A4007D6C76 /* ASDataController+Subclasses.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF61BBB3D690087C538 /* ASDataController+Subclasses.h */; };
|
||||
9C70F20C1CDBE9B6007D6C76 /* ASCollectionDataController.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF21BBB3D690087C538 /* ASCollectionDataController.h */; };
|
||||
9C70F20D1CDBE9CB007D6C76 /* ASDefaultPlayButton.h in Headers */ = {isa = PBXBuildFile; fileRef = AEB7B0181C5962EA00662EF4 /* ASDefaultPlayButton.h */; };
|
||||
9C70F20E1CDBE9E5007D6C76 /* NSArray+Diffing.h in Headers */ = {isa = PBXBuildFile; fileRef = DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */; };
|
||||
9C70F20F1CDBE9FF007D6C76 /* ASLayoutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */; };
|
||||
9C8221951BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C8221931BA237B80037F19A /* ASStackBaselinePositionedLayout.h */; };
|
||||
9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C8221931BA237B80037F19A /* ASStackBaselinePositionedLayout.h */; };
|
||||
9C8221971BA237B80037F19A /* ASStackBaselinePositionedLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C8221941BA237B80037F19A /* ASStackBaselinePositionedLayout.mm */; };
|
||||
@ -336,6 +357,9 @@
|
||||
9C8898BD1C738BB800D6B02E /* ASTextKitFontSizeAdjuster.h in Headers */ = {isa = PBXBuildFile; fileRef = A32FEDD31C501B6A004F642A /* ASTextKitFontSizeAdjuster.h */; };
|
||||
9CDC18CC1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9CDC18CD1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9CFFC6BE1CCAC52B006A6476 /* ASEnvironment.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */; };
|
||||
9CFFC6C01CCAC73C006A6476 /* ASViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */; };
|
||||
9CFFC6C21CCAC768006A6476 /* ASTableNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */; };
|
||||
9F06E5CD1B4CAF4200F015D8 /* ASCollectionViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */; };
|
||||
A2763D791CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */; };
|
||||
A2763D7A1CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */; };
|
||||
@ -362,7 +386,6 @@
|
||||
AC7A2C171BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */; };
|
||||
AC7A2C181BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */; };
|
||||
ACC945A91BA9E7A0005E1FB8 /* ASViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
ACC945AB1BA9E7C1005E1FB8 /* ASViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */; };
|
||||
ACF6ED1A1B17843500DA7C62 /* ASBackgroundLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED011B17843500DA7C62 /* ASBackgroundLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
ACF6ED1B1B17843500DA7C62 /* ASBackgroundLayoutSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED021B17843500DA7C62 /* ASBackgroundLayoutSpec.mm */; };
|
||||
ACF6ED1C1B17843500DA7C62 /* ASCenterLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED031B17843500DA7C62 /* ASCenterLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -405,7 +428,6 @@
|
||||
AEEC47E21C20C2DD00EC1693 /* ASVideoNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E01C20C2DD00EC1693 /* ASVideoNode.mm */; };
|
||||
AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */; };
|
||||
B0F8805A1BEAEC7500D17647 /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
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 */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -499,7 +521,6 @@
|
||||
B350625D1B0111740018CF92 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943141A1575670030A7D0 /* Photos.framework */; };
|
||||
B350625E1B0111780018CF92 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943121A1575630030A7D0 /* AssetsLibrary.framework */; };
|
||||
B350625F1B0111800018CF92 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AF195D04C000B7D73C /* Foundation.framework */; };
|
||||
C78F7E2A1BF7808300CDEAFC /* ASTableNode.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F880591BEAEC7500D17647 /* ASTableNode.m */; };
|
||||
C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
CC3B20831C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; };
|
||||
CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; };
|
||||
@ -778,8 +799,13 @@
|
||||
68B8A4E01CBDB958007E4543 /* ASWeakProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakProxy.m; sourceTree = "<group>"; };
|
||||
68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMainSerialQueue.h; sourceTree = "<group>"; };
|
||||
68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMainSerialQueue.mm; sourceTree = "<group>"; };
|
||||
68FC85DC1CE29AB700EDD713 /* ASNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASNavigationController.h; sourceTree = "<group>"; };
|
||||
68FC85DD1CE29AB700EDD713 /* ASNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASNavigationController.m; sourceTree = "<group>"; };
|
||||
68FC85E01CE29B7E00EDD713 /* ASTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTabBarController.h; sourceTree = "<group>"; };
|
||||
68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTabBarController.m; sourceTree = "<group>"; };
|
||||
68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASVisibilityProtocols.h; sourceTree = "<group>"; };
|
||||
68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASVisibilityProtocols.m; sourceTree = "<group>"; };
|
||||
698548611CA9E025008A345F /* ASEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEnvironment.h; sourceTree = "<group>"; };
|
||||
698548621CA9E025008A345F /* ASEnvironment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASEnvironment.m; sourceTree = "<group>"; };
|
||||
698C8B601CAB49FC0052DC3F /* ASLayoutableExtensibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutableExtensibility.h; path = AsyncDisplayKit/Layout/ASLayoutableExtensibility.h; sourceTree = "<group>"; };
|
||||
69CB62A91CB8165900024920 /* _ASDisplayViewAccessiblity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASDisplayViewAccessiblity.h; sourceTree = "<group>"; };
|
||||
69CB62AA1CB8165900024920 /* _ASDisplayViewAccessiblity.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASDisplayViewAccessiblity.mm; sourceTree = "<group>"; };
|
||||
@ -805,10 +831,15 @@
|
||||
9C5586671BD549CB00B50E3A /* ASAsciiArtBoxCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASAsciiArtBoxCreator.h; path = AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.h; sourceTree = "<group>"; };
|
||||
9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASAsciiArtBoxCreator.m; path = AsyncDisplayKit/Layout/ASAsciiArtBoxCreator.m; sourceTree = "<group>"; };
|
||||
9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStaticLayoutable.h; path = AsyncDisplayKit/Layout/ASStaticLayoutable.h; sourceTree = "<group>"; };
|
||||
9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTraitCollection.h; sourceTree = "<group>"; };
|
||||
9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTraitCollection.m; sourceTree = "<group>"; };
|
||||
9C8221931BA237B80037F19A /* ASStackBaselinePositionedLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackBaselinePositionedLayout.h; sourceTree = "<group>"; };
|
||||
9C8221941BA237B80037F19A /* ASStackBaselinePositionedLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackBaselinePositionedLayout.mm; sourceTree = "<group>"; };
|
||||
9C8898BA1C738B9800D6B02E /* ASTextKitFontSizeAdjuster.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitFontSizeAdjuster.mm; path = TextKit/ASTextKitFontSizeAdjuster.mm; sourceTree = "<group>"; };
|
||||
9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutablePrivate.h; path = AsyncDisplayKit/Layout/ASLayoutablePrivate.h; sourceTree = "<group>"; };
|
||||
9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEnvironment.mm; sourceTree = "<group>"; };
|
||||
9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASViewController.mm; sourceTree = "<group>"; };
|
||||
9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTableNode.mm; sourceTree = "<group>"; };
|
||||
9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASCollectionViewTests.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
|
||||
A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASPINRemoteImageDownloader.h; path = Details/ASPINRemoteImageDownloader.h; sourceTree = "<group>"; };
|
||||
A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASPINRemoteImageDownloader.m; path = Details/ASPINRemoteImageDownloader.m; sourceTree = "<group>"; };
|
||||
@ -828,7 +859,6 @@
|
||||
AC6456071B0A335000CF11B8 /* ASCellNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCellNode.mm; sourceTree = "<group>"; };
|
||||
AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTableViewInternal.h; sourceTree = "<group>"; };
|
||||
ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASViewController.h; sourceTree = "<group>"; };
|
||||
ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASViewController.m; sourceTree = "<group>"; };
|
||||
ACF6ED011B17843500DA7C62 /* ASBackgroundLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASBackgroundLayoutSpec.h; path = AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h; sourceTree = "<group>"; };
|
||||
ACF6ED021B17843500DA7C62 /* ASBackgroundLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = ASBackgroundLayoutSpec.mm; path = AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm; sourceTree = "<group>"; };
|
||||
ACF6ED031B17843500DA7C62 /* ASCenterLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASCenterLayoutSpec.h; path = AsyncDisplayKit/Layout/ASCenterLayoutSpec.h; sourceTree = "<group>"; };
|
||||
@ -872,7 +902,6 @@
|
||||
AEEC47E01C20C2DD00EC1693 /* ASVideoNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASVideoNode.mm; sourceTree = "<group>"; };
|
||||
AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASVideoNodeTests.m; sourceTree = "<group>"; };
|
||||
B0F880581BEAEC7500D17647 /* ASTableNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTableNode.h; sourceTree = "<group>"; };
|
||||
B0F880591BEAEC7500D17647 /* ASTableNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableNode.m; sourceTree = "<group>"; };
|
||||
B13CA0F61C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionViewLayoutFacilitatorProtocol.h; sourceTree = "<group>"; };
|
||||
B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionNode+Beta.h"; sourceTree = "<group>"; };
|
||||
B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutManager.h; path = TextKit/ASLayoutManager.h; sourceTree = "<group>"; };
|
||||
@ -1064,6 +1093,8 @@
|
||||
68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */,
|
||||
0516FA3E1A1563D200B4EBED /* ASMultiplexImageNode.h */,
|
||||
0516FA3F1A1563D200B4EBED /* ASMultiplexImageNode.mm */,
|
||||
68FC85DC1CE29AB700EDD713 /* ASNavigationController.h */,
|
||||
68FC85DD1CE29AB700EDD713 /* ASNavigationController.m */,
|
||||
055B9FA61A1C154B00035D6D /* ASNetworkImageNode.h */,
|
||||
055B9FA71A1C154B00035D6D /* ASNetworkImageNode.mm */,
|
||||
25E327541C16819500A2170C /* ASPagerNode.h */,
|
||||
@ -1072,8 +1103,10 @@
|
||||
A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.m */,
|
||||
D785F6601A74327E00291744 /* ASScrollNode.h */,
|
||||
D785F6611A74327E00291744 /* ASScrollNode.m */,
|
||||
68FC85E01CE29B7E00EDD713 /* ASTabBarController.h */,
|
||||
68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */,
|
||||
B0F880581BEAEC7500D17647 /* ASTableNode.h */,
|
||||
B0F880591BEAEC7500D17647 /* ASTableNode.m */,
|
||||
9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */,
|
||||
055F1A3219ABD3E3004DAFF1 /* ASTableView.h */,
|
||||
055F1A3319ABD3E3004DAFF1 /* ASTableView.mm */,
|
||||
AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */,
|
||||
@ -1082,11 +1115,13 @@
|
||||
A373200E1C571B050011FC94 /* ASTextNode+Beta.h */,
|
||||
058D09E0195D050800B7D73C /* ASTextNode.mm */,
|
||||
ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */,
|
||||
ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */,
|
||||
9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */,
|
||||
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */,
|
||||
764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */,
|
||||
764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */,
|
||||
DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */,
|
||||
68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */,
|
||||
68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */,
|
||||
92074A5E1CC8B9DD00918F75 /* tvOS */,
|
||||
058D09E1195D050800B7D73C /* Details */,
|
||||
058D0A01195D050800B7D73C /* Private */,
|
||||
@ -1167,6 +1202,7 @@
|
||||
058D09E1195D050800B7D73C /* Details */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */,
|
||||
058D09E2195D050800B7D73C /* _ASDisplayLayer.h */,
|
||||
058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */,
|
||||
058D09E4195D050800B7D73C /* _ASDisplayView.h */,
|
||||
@ -1187,7 +1223,6 @@
|
||||
05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */,
|
||||
05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */,
|
||||
698548611CA9E025008A345F /* ASEnvironment.h */,
|
||||
698548621CA9E025008A345F /* ASEnvironment.m */,
|
||||
4640521B1A3F83C40061C0BA /* ASFlowLayoutController.h */,
|
||||
4640521C1A3F83C40061C0BA /* ASFlowLayoutController.mm */,
|
||||
058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */,
|
||||
@ -1226,6 +1261,8 @@
|
||||
205F0E0D1B371875007741D0 /* UICollectionViewLayout+ASConvenience.h */,
|
||||
205F0E0E1B371875007741D0 /* UICollectionViewLayout+ASConvenience.m */,
|
||||
058D09FF195D050800B7D73C /* UIView+ASConvenience.h */,
|
||||
9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */,
|
||||
9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */,
|
||||
);
|
||||
path = Details;
|
||||
sourceTree = "<group>";
|
||||
@ -1480,6 +1517,7 @@
|
||||
058D0A82195D060300B7D73C /* ASAssert.h in Headers */,
|
||||
0516FA3C1A15563400B4EBED /* ASAvailability.h in Headers */,
|
||||
AEB7B01A1C5962EA00662EF4 /* ASDefaultPlayButton.h in Headers */,
|
||||
68FC85E21CE29B7E00EDD713 /* ASTabBarController.h in Headers */,
|
||||
ACF6ED1A1B17843500DA7C62 /* ASBackgroundLayoutSpec.h in Headers */,
|
||||
058D0A83195D060300B7D73C /* ASBaseDefines.h in Headers */,
|
||||
054963491A1EA066000F8E56 /* ASBasicImageDownloader.h in Headers */,
|
||||
@ -1495,6 +1533,7 @@
|
||||
AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */,
|
||||
AEEC47E11C20C2DD00EC1693 /* ASVideoNode.h in Headers */,
|
||||
DE8BEAC11C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */,
|
||||
68FC85DE1CE29AB700EDD713 /* ASNavigationController.h in Headers */,
|
||||
205F0E1D1B373A2C007741D0 /* ASCollectionViewLayoutController.h in Headers */,
|
||||
AC3C4A541A113EEC00143C57 /* ASCollectionViewProtocols.h in Headers */,
|
||||
058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */,
|
||||
@ -1520,9 +1559,11 @@
|
||||
0587F9BD1A7309ED00AFF0BA /* ASEditableTextNode.h in Headers */,
|
||||
DE6EA3221C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */,
|
||||
1950C4491A3BB5C1005C8279 /* ASEqualityHelpers.h in Headers */,
|
||||
68FC85E91CE29C7D00EDD713 /* ASVisibilityProtocols.h in Headers */,
|
||||
257754A81BEE44CD00737CA5 /* ASTextKitContext.h in Headers */,
|
||||
DB55C2611C6408D6004EDCF5 /* _ASTransitionContext.h in Headers */,
|
||||
464052221A3F83C40061C0BA /* ASFlowLayoutController.h in Headers */,
|
||||
9C70F2031CDA4EFA007D6C76 /* ASTraitCollection.h in Headers */,
|
||||
257754AF1BEE44CD00737CA5 /* ASTextKitRenderer+TextChecking.h in Headers */,
|
||||
058D0A57195D05DC00B7D73C /* ASHighlightOverlayLayer.h in Headers */,
|
||||
058D0A7C195D05F900B7D73C /* ASImageNode+CGExtras.h in Headers */,
|
||||
@ -1607,6 +1648,7 @@
|
||||
B35062481B010EFD0018CF92 /* _AS-objc-internal.h in Headers */,
|
||||
69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */,
|
||||
B350623C1B010EFD0018CF92 /* _ASAsyncTransaction.h in Headers */,
|
||||
9C70F20D1CDBE9CB007D6C76 /* ASDefaultPlayButton.h in Headers */,
|
||||
68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */,
|
||||
7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */,
|
||||
B350623F1B010EFD0018CF92 /* _ASAsyncTransactionContainer.h in Headers */,
|
||||
@ -1643,6 +1685,7 @@
|
||||
AC026B701BD57DBF00BBC17E /* _ASHierarchyChangeSet.h in Headers */,
|
||||
B35061F31B010EFD0018CF92 /* ASCellNode.h in Headers */,
|
||||
34EFC7631B701CBF00AD841F /* ASCenterLayoutSpec.h in Headers */,
|
||||
9C70F20C1CDBE9B6007D6C76 /* ASCollectionDataController.h in Headers */,
|
||||
18C2ED7F1B9B7DE800F627B3 /* ASCollectionNode.h in Headers */,
|
||||
9C8898BD1C738BB800D6B02E /* ASTextKitFontSizeAdjuster.h in Headers */,
|
||||
B35061F51B010EFD0018CF92 /* ASCollectionView.h in Headers */,
|
||||
@ -1651,14 +1694,18 @@
|
||||
CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */,
|
||||
92074A621CC8BA1900918F75 /* ASImageNode+tvOS.h in Headers */,
|
||||
B35061F71B010EFD0018CF92 /* ASCollectionViewProtocols.h in Headers */,
|
||||
68FC85E31CE29B7E00EDD713 /* ASTabBarController.h in Headers */,
|
||||
DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */,
|
||||
9C70F20F1CDBE9FF007D6C76 /* ASLayoutManager.h in Headers */,
|
||||
B35061FA1B010EFD0018CF92 /* ASControlNode+Subclasses.h in Headers */,
|
||||
B35061F81B010EFD0018CF92 /* ASControlNode.h in Headers */,
|
||||
B35062171B010EFD0018CF92 /* ASDataController.h in Headers */,
|
||||
B35062191B010EFD0018CF92 /* ASDealloc2MainObject.h in Headers */,
|
||||
34EFC75B1B701BAF00AD841F /* ASDimension.h in Headers */,
|
||||
68FC85EA1CE29C7D00EDD713 /* ASVisibilityProtocols.h in Headers */,
|
||||
A37320101C571B740011FC94 /* ASTextNode+Beta.h in Headers */,
|
||||
DBABFAFC1C6A8D2F0039EA4A /* _ASTransitionContext.h in Headers */,
|
||||
9C70F2061CDA4F0C007D6C76 /* ASTraitCollection.h in Headers */,
|
||||
254C6B801BF94DF4003EC431 /* ASEqualityHashHelpers.h in Headers */,
|
||||
B350624F1B010EFD0018CF92 /* ASDisplayNode+DebugTiming.h in Headers */,
|
||||
B35061FD1B010EFD0018CF92 /* ASDisplayNode+Subclasses.h in Headers */,
|
||||
@ -1667,6 +1714,7 @@
|
||||
B35062521B010EFD0018CF92 /* ASDisplayNodeInternal.h in Headers */,
|
||||
B35062001B010EFD0018CF92 /* ASEditableTextNode.h in Headers */,
|
||||
B350625B1B010F070018CF92 /* ASEqualityHelpers.h in Headers */,
|
||||
680346941CE4052A0009FEB4 /* ASNavigationController.h in Headers */,
|
||||
B350621B1B010EFD0018CF92 /* ASFlowLayoutController.h in Headers */,
|
||||
B350621D1B010EFD0018CF92 /* ASHighlightOverlayLayer.h in Headers */,
|
||||
C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */,
|
||||
@ -1677,6 +1725,7 @@
|
||||
B35062021B010EFD0018CF92 /* ASImageNode.h in Headers */,
|
||||
B350621F1B010EFD0018CF92 /* ASImageProtocols.h in Headers */,
|
||||
430E7C901B4C23F100697A4C /* ASIndexPath.h in Headers */,
|
||||
9C70F20B1CDBE9A4007D6C76 /* ASDataController+Subclasses.h in Headers */,
|
||||
34EFC75F1B701C8600AD841F /* ASInsetLayoutSpec.h in Headers */,
|
||||
34EFC75D1B701BE900AD841F /* ASInternalHelpers.h in Headers */,
|
||||
34EFC7671B701CD900AD841F /* ASLayout.h in Headers */,
|
||||
@ -1712,6 +1761,7 @@
|
||||
25E327571C16819500A2170C /* ASPagerNode.h in Headers */,
|
||||
B35062551B010EFD0018CF92 /* ASSentinel.h in Headers */,
|
||||
9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */,
|
||||
9C70F20E1CDBE9E5007D6C76 /* NSArray+Diffing.h in Headers */,
|
||||
9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */,
|
||||
DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */,
|
||||
34EFC7701B701CFA00AD841F /* ASStackLayoutDefines.h in Headers */,
|
||||
@ -1955,6 +2005,7 @@
|
||||
files = (
|
||||
058D0A22195D050800B7D73C /* _ASAsyncTransaction.mm in Sources */,
|
||||
E55D86321CA8A14000A0C26F /* ASLayoutable.mm in Sources */,
|
||||
68FC85E41CE29B7E00EDD713 /* ASTabBarController.m in Sources */,
|
||||
058D0A23195D050800B7D73C /* _ASAsyncTransactionContainer.m in Sources */,
|
||||
058D0A24195D050800B7D73C /* _ASAsyncTransactionGroup.m in Sources */,
|
||||
68355B3A1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m in Sources */,
|
||||
@ -1982,7 +2033,9 @@
|
||||
92DD2FE41BF4B97E0074C9DD /* ASMapNode.mm in Sources */,
|
||||
DBC452DC1C5BF64600B16017 /* NSArray+Diffing.m in Sources */,
|
||||
AC3C4A521A1139C100143C57 /* ASCollectionView.mm in Sources */,
|
||||
9CFFC6C21CCAC768006A6476 /* ASTableNode.mm in Sources */,
|
||||
205F0E1E1B373A2C007741D0 /* ASCollectionViewLayoutController.mm in Sources */,
|
||||
68FC85EB1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */,
|
||||
058D0A13195D050800B7D73C /* ASControlNode.mm in Sources */,
|
||||
464052211A3F83C40061C0BA /* ASDataController.mm in Sources */,
|
||||
B30BF6531C5964B0004FCD53 /* ASLayoutManager.m in Sources */,
|
||||
@ -2007,7 +2060,7 @@
|
||||
430E7C911B4C23F100697A4C /* ASIndexPath.m in Sources */,
|
||||
ACF6ED231B17843500DA7C62 /* ASInsetLayoutSpec.mm in Sources */,
|
||||
ACF6ED4C1B17847A00DA7C62 /* ASInternalHelpers.mm in Sources */,
|
||||
698548651CA9E025008A345F /* ASEnvironment.m in Sources */,
|
||||
68FC85DF1CE29AB700EDD713 /* ASNavigationController.m in Sources */,
|
||||
ACF6ED251B17843500DA7C62 /* ASLayout.mm in Sources */,
|
||||
DB55C2631C6408D6004EDCF5 /* _ASTransitionContext.m in Sources */,
|
||||
92074A631CC8BA1900918F75 /* ASImageNode+tvOS.m in Sources */,
|
||||
@ -2046,17 +2099,18 @@
|
||||
ACF6ED521B17847A00DA7C62 /* ASStackUnpositionedLayout.mm in Sources */,
|
||||
257754A61BEE44CD00737CA5 /* ASTextKitAttributes.mm in Sources */,
|
||||
81EE38501C8E94F000456208 /* ASRunLoopQueue.mm in Sources */,
|
||||
9C70F2041CDA4EFA007D6C76 /* ASTraitCollection.m in Sources */,
|
||||
92074A691CC8BADA00918F75 /* ASControlNode+tvOS.m in Sources */,
|
||||
ACF6ED321B17843500DA7C62 /* ASStaticLayoutSpec.mm in Sources */,
|
||||
AC026B6B1BD57D6F00BBC17E /* ASChangeSetDataController.m in Sources */,
|
||||
68355B311CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */,
|
||||
9CFFC6C01CCAC73C006A6476 /* ASViewController.mm in Sources */,
|
||||
055F1A3519ABD3E3004DAFF1 /* ASTableView.mm in Sources */,
|
||||
058D0A17195D050800B7D73C /* ASTextNode.mm in Sources */,
|
||||
257754AC1BEE44CD00737CA5 /* ASTextKitRenderer.mm in Sources */,
|
||||
ACC945AB1BA9E7C1005E1FB8 /* ASViewController.m in Sources */,
|
||||
B0F8805B1BEAEC7500D17647 /* ASTableNode.m in Sources */,
|
||||
205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */,
|
||||
257754B21BEE44CD00737CA5 /* ASTextKitShadower.mm in Sources */,
|
||||
9CFFC6BE1CCAC52B006A6476 /* ASEnvironment.mm in Sources */,
|
||||
058D0A21195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m in Sources */,
|
||||
205F0E101B371875007741D0 /* UICollectionViewLayout+ASConvenience.m in Sources */,
|
||||
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */,
|
||||
@ -2109,6 +2163,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9C70F2091CDABA36007D6C76 /* ASViewController.mm in Sources */,
|
||||
DE4843DB1C93EAB100A1F33B /* ASDisplayNodeLayoutContext.mm in Sources */,
|
||||
B30BF6541C59D889004FCD53 /* ASLayoutManager.m in Sources */,
|
||||
92DD2FE71BF4D0850074C9DD /* ASMapNode.mm in Sources */,
|
||||
@ -2121,8 +2176,6 @@
|
||||
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 */,
|
||||
B35062121B010EFD0018CF92 /* _ASDisplayView.mm in Sources */,
|
||||
@ -2134,13 +2187,16 @@
|
||||
9C8898BC1C738BA800D6B02E /* ASTextKitFontSizeAdjuster.mm in Sources */,
|
||||
34EFC7621B701CA400AD841F /* ASBackgroundLayoutSpec.mm in Sources */,
|
||||
DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */,
|
||||
9C70F2081CDAA3C6007D6C76 /* ASEnvironment.mm in Sources */,
|
||||
B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */,
|
||||
B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */,
|
||||
AC47D9421B3B891B00AAEE9D /* ASCellNode.mm in Sources */,
|
||||
34EFC7641B701CC600AD841F /* ASCenterLayoutSpec.mm in Sources */,
|
||||
18C2ED831B9B7DE800F627B3 /* ASCollectionNode.mm in Sources */,
|
||||
E55D86331CA8A14000A0C26F /* ASLayoutable.mm in Sources */,
|
||||
68FC85EC1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */,
|
||||
68B8A4E41CBDB958007E4543 /* ASWeakProxy.m in Sources */,
|
||||
9C70F20A1CDBE949007D6C76 /* ASTableNode.mm in Sources */,
|
||||
69CB62AE1CB8165900024920 /* _ASDisplayViewAccessiblity.mm in Sources */,
|
||||
B35061F61B010EFD0018CF92 /* ASCollectionView.mm in Sources */,
|
||||
509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.mm in Sources */,
|
||||
@ -2187,6 +2243,7 @@
|
||||
044285101BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm in Sources */,
|
||||
B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */,
|
||||
0442850A1BAA63FE00D16268 /* ASBatchFetching.m in Sources */,
|
||||
68FC85E61CE29B9400EDD713 /* ASNavigationController.m in Sources */,
|
||||
34EFC76F1B701CF700AD841F /* ASRatioLayoutSpec.mm in Sources */,
|
||||
254C6B8B1BF94F8A003EC431 /* ASTextKitShadower.mm in Sources */,
|
||||
34EFC7661B701CD200AD841F /* ASRelativeSize.mm in Sources */,
|
||||
@ -2198,8 +2255,10 @@
|
||||
34EFC7721B701D0300AD841F /* ASStackLayoutSpec.mm in Sources */,
|
||||
34EFC7761B701D2A00AD841F /* ASStackPositionedLayout.mm in Sources */,
|
||||
7AB338661C55B3420055FDE8 /* ASRelativeLayoutSpec.mm in Sources */,
|
||||
9C70F2051CDA4F06007D6C76 /* ASTraitCollection.m in Sources */,
|
||||
34EFC7781B701D3100AD841F /* ASStackUnpositionedLayout.mm in Sources */,
|
||||
DE84918E1C8FFF9F003D89E9 /* ASRunLoopQueue.mm in Sources */,
|
||||
68FC85E51CE29B7E00EDD713 /* ASTabBarController.m in Sources */,
|
||||
AC026B6C1BD57D6F00BBC17E /* ASChangeSetDataController.m in Sources */,
|
||||
34EFC7741B701D0A00AD841F /* ASStaticLayoutSpec.mm in Sources */,
|
||||
92074A6A1CC8BADA00918F75 /* ASControlNode+tvOS.m in Sources */,
|
||||
@ -2207,7 +2266,6 @@
|
||||
B350620B1B010EFD0018CF92 /* ASTableView.mm in Sources */,
|
||||
B350620E1B010EFD0018CF92 /* ASTextNode.mm in Sources */,
|
||||
68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */,
|
||||
C78F7E2A1BF7808300CDEAFC /* ASTableNode.m in Sources */,
|
||||
509E68661B3AEDD7009B9150 /* CGRect+ASConvenience.m in Sources */,
|
||||
254C6B8D1BF94F8A003EC431 /* ASEqualityHashHelpers.mm in Sources */,
|
||||
254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.m in Sources */,
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#import "ASCollectionInternal.h"
|
||||
#import "ASCollectionViewLayoutFacilitatorProtocol.h"
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASRangeControllerUpdateRangeProtocol+Beta.h"
|
||||
#include <vector>
|
||||
|
||||
@ -53,6 +54,9 @@
|
||||
#endif
|
||||
|
||||
@interface ASCollectionNode ()
|
||||
{
|
||||
ASDN::RecursiveMutex _environmentStateLock;
|
||||
}
|
||||
@property (nonatomic) _ASCollectionPendingState *pendingState;
|
||||
@end
|
||||
|
||||
@ -244,4 +248,6 @@
|
||||
[self.view reloadDataImmediately];
|
||||
}
|
||||
|
||||
ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock)
|
||||
|
||||
@end
|
||||
|
||||
@ -342,7 +342,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* This is a node-based UICollectionViewDataSource.
|
||||
*/
|
||||
#define ASCollectionViewDataSource ASCollectionDataSource
|
||||
@protocol ASCollectionDataSource <ASCommonCollectionViewDataSource, NSObject>
|
||||
@protocol ASCollectionDataSource <ASCommonCollectionViewDataSource>
|
||||
|
||||
@optional
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
#pragma mark -
|
||||
#pragma mark ASCollectionView.
|
||||
|
||||
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView> {
|
||||
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView, ASDataControllerEnvironmentDelegate> {
|
||||
ASCollectionViewProxy *_proxyDataSource;
|
||||
ASCollectionViewProxy *_proxyDelegate;
|
||||
|
||||
@ -225,6 +225,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
_dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:NO];
|
||||
_dataController.delegate = _rangeController;
|
||||
_dataController.dataSource = self;
|
||||
_dataController.environmentDelegate = self;
|
||||
|
||||
_batchContext = [[ASBatchContext alloc] init];
|
||||
|
||||
@ -343,10 +344,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
{
|
||||
// Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle
|
||||
// the (common) case of nilling the asyncDataSource in the ViewController's dealloc. In this case our _asyncDataSource
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to nil out
|
||||
// super.dataSource in this case because calls to ASCollectionViewProxy will start failing and cause crashes.
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
|
||||
// reference to the old dataSource in this case because calls to ASCollectionViewProxy will start failing and cause crashes.
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id oldDataSource = super.dataSource;
|
||||
|
||||
super.dataSource = nil;
|
||||
if (asyncDataSource == nil) {
|
||||
_asyncDataSource = nil;
|
||||
_proxyDataSource = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self];
|
||||
@ -375,13 +376,9 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
{
|
||||
// Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle
|
||||
// the (common) case of nilling the asyncDelegate in the ViewController's dealloc. In this case our _asyncDelegate
|
||||
// will return as nil (ARC magic) even though the _proxyDelegate still exists. It's really important to nil out
|
||||
// super.delegate in this case because calls to ASCollectionViewProxy will start failing and cause crashes.
|
||||
|
||||
// Order is important here, the asyncDelegate must be callable while nilling super.delegate to avoid random crashes
|
||||
// in UIScrollViewAccessibility.
|
||||
|
||||
super.delegate = nil;
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
|
||||
// reference to the old delegate in this case because calls to ASCollectionViewProxy will start failing and cause crashes.
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id oldDelegate = super.delegate;
|
||||
|
||||
if (asyncDelegate == nil) {
|
||||
_asyncDelegate = nil;
|
||||
@ -921,6 +918,14 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
- (id<ASEnvironment>)dataControllerEnvironment
|
||||
{
|
||||
if (self.collectionNode) {
|
||||
return self.collectionNode;
|
||||
}
|
||||
return self.strongCollectionNode;
|
||||
}
|
||||
|
||||
#pragma mark - ASCollectionViewDataControllerSource Supplementary view support
|
||||
|
||||
- (ASCellNode *)dataController:(ASCollectionDataController *)dataController supplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#import "_ASCoreAnimationExtras.h"
|
||||
#import "ASDisplayNodeLayoutContext.h"
|
||||
#import "ASDisplayNodeExtras.h"
|
||||
#import "ASTraitCollection.h"
|
||||
#import "ASEqualityHelpers.h"
|
||||
#import "ASRunLoopQueue.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
@ -2710,9 +2711,24 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority";
|
||||
return ASEnvironmentStatePropagationEnabled();
|
||||
}
|
||||
|
||||
- (BOOL)supportsTraitsCollectionPropagation
|
||||
{
|
||||
return ASEnvironmentStateTraitCollectionPropagationEnabled();
|
||||
}
|
||||
|
||||
- (ASEnvironmentTraitCollection)environmentTraitCollection
|
||||
{
|
||||
return _environmentState.traitCollection;
|
||||
}
|
||||
|
||||
ASEnvironmentLayoutOptionsForwarding
|
||||
ASEnvironmentLayoutExtensibilityForwarding
|
||||
|
||||
- (ASTraitCollection *)asyncTraitCollection
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return [ASTraitCollection traitCollectionWithASEnvironmentTraitCollection:_environmentState.traitCollection];
|
||||
}
|
||||
|
||||
#if TARGET_OS_TV
|
||||
#pragma mark - UIFocusEnvironment Protocol (tvOS)
|
||||
|
||||
@ -117,13 +117,20 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) {
|
||||
*/
|
||||
@property (nullable, nonatomic, readonly) ASImageIdentifier displayedImageIdentifier;
|
||||
|
||||
/**
|
||||
* @abstract If the downloader implements progressive image rendering and this value is YES progressive renders of the
|
||||
* image will be displayed as the image downloads. Regardless of this properties value, progress renders will
|
||||
* only occur when the node is visible. Defaults to YES.
|
||||
*/
|
||||
@property (nonatomic, assign, readwrite) BOOL shouldRenderProgressImages;
|
||||
|
||||
#if TARGET_OS_IOS
|
||||
/**
|
||||
* @abstract The image manager that this image node should use when requesting images from the Photos framework. If this is `nil` (the default), then `PHImageManager.defaultManager` is used.
|
||||
|
||||
* @see `+[NSURL URLWithAssetLocalIdentifier:targetSize:contentMode:options:]` below.
|
||||
*/
|
||||
@property (nonatomic, strong) PHImageManager *imageManager;
|
||||
@property (nullable, nonatomic, strong) PHImageManager *imageManager;
|
||||
#endif
|
||||
@end
|
||||
|
||||
|
||||
@ -85,6 +85,10 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
ASDN::RecursiveMutex _downloadIdentifierLock;
|
||||
id _downloadIdentifier;
|
||||
|
||||
// Properties
|
||||
ASDN::RecursiveMutex _propertyLock;
|
||||
BOOL _shouldRenderProgressImages;
|
||||
|
||||
//set on init only
|
||||
BOOL _downloaderSupportsNewProtocol;
|
||||
BOOL _downloaderImplementsSetProgress;
|
||||
@ -186,6 +190,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
_cacheSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)];
|
||||
_cacheSupportsClearing = [cache respondsToSelector:@selector(clearFetchedImageFromCacheWithURL:)];
|
||||
|
||||
_shouldRenderProgressImages = YES;
|
||||
|
||||
self.shouldBypassEnsureDisplay = YES;
|
||||
|
||||
return self;
|
||||
@ -339,6 +345,27 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
- (void)setShouldRenderProgressImages:(BOOL)shouldRenderProgressImages
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
if (shouldRenderProgressImages == _shouldRenderProgressImages) {
|
||||
return;
|
||||
}
|
||||
|
||||
_shouldRenderProgressImages = shouldRenderProgressImages;
|
||||
|
||||
|
||||
ASDN::MutexUnlocker u(_propertyLock);
|
||||
[self _updateProgressImageBlockOnDownloaderIfNeeded];
|
||||
}
|
||||
|
||||
- (BOOL)shouldRenderProgressImages
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _shouldRenderProgressImages;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
#pragma mark -
|
||||
@ -436,8 +463,12 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
}
|
||||
|
||||
// Grab the best available image from the data source.
|
||||
UIImage *existingImage = self.image;
|
||||
for (id imageIdentifier in _imageIdentifiers) {
|
||||
UIImage *image = [_dataSource multiplexImageNode:self imageForImageIdentifier:imageIdentifier];
|
||||
// If this image is already loaded, don't request it from the data source again because
|
||||
// the data source may generate a new instance of UIImage that returns NO for isEqual:
|
||||
// and we'll end up in an infinite loading loop.
|
||||
UIImage *image = ASObjectIsEqual(imageIdentifier, _loadedImageIdentifier) ? existingImage : [_dataSource multiplexImageNode:self imageForImageIdentifier:imageIdentifier];
|
||||
if (image) {
|
||||
if (imageIdentifierOut) {
|
||||
*imageIdentifierOut = imageIdentifier;
|
||||
@ -458,32 +489,34 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
*/
|
||||
- (void)_updateProgressImageBlockOnDownloaderIfNeeded
|
||||
{
|
||||
// Read our interface state before locking so that we don't lock super while holding our lock.
|
||||
ASInterfaceState interfaceState = self.interfaceState;
|
||||
ASDN::MutexLocker l(_downloadIdentifierLock);
|
||||
BOOL shouldRenderProgressImages = self.shouldRenderProgressImages;
|
||||
|
||||
if (!_downloaderImplementsSetProgress || _downloadIdentifier == nil) {
|
||||
// Read our interface state before locking so that we don't lock super while holding our lock.
|
||||
ASInterfaceState interfaceState = self.interfaceState;
|
||||
ASDN::MutexLocker l(_downloadIdentifierLock);
|
||||
|
||||
if (!_downloaderImplementsSetProgress || _downloadIdentifier == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASImageDownloaderProgressImage progress = nil;
|
||||
if (shouldRenderProgressImages && ASInterfaceStateIncludesVisible(interfaceState)) {
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
progress = ^(UIImage * _Nonnull progressImage, CGFloat progress, id _Nullable downloadIdentifier) {
|
||||
__typeof__(self) strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ASImageDownloaderProgressImage progress = nil;
|
||||
if (ASInterfaceStateIncludesVisible(interfaceState)) {
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
progress = ^(UIImage * _Nonnull progressImage, CGFloat progress, id _Nullable downloadIdentifier) {
|
||||
__typeof__(self) strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASDN::MutexLocker l(strongSelf->_downloadIdentifierLock);
|
||||
//Getting a result back for a different download identifier, download must not have been successfully canceled
|
||||
if (ASObjectIsEqual(strongSelf->_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) {
|
||||
return;
|
||||
}
|
||||
strongSelf.image = progressImage;
|
||||
};
|
||||
}
|
||||
[_downloader setProgressImageBlock:progress callbackQueue:dispatch_get_main_queue() withDownloadIdentifier:_downloadIdentifier];
|
||||
ASDN::MutexLocker l(strongSelf->_downloadIdentifierLock);
|
||||
//Getting a result back for a different download identifier, download must not have been successfully canceled
|
||||
if (ASObjectIsEqual(strongSelf->_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) {
|
||||
return;
|
||||
}
|
||||
strongSelf.image = progressImage;
|
||||
};
|
||||
}
|
||||
[_downloader setProgressImageBlock:progress callbackQueue:dispatch_get_main_queue() withDownloadIdentifier:_downloadIdentifier];
|
||||
}
|
||||
|
||||
- (void)_clearImage
|
||||
|
||||
15
AsyncDisplayKit/ASNavigationController.h
Normal file
15
AsyncDisplayKit/ASNavigationController.h
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// ASNavigationController.h
|
||||
// Pods
|
||||
//
|
||||
// Created by Garrett Moon on 4/27/16.
|
||||
//
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "ASVisibilityProtocols.h"
|
||||
|
||||
@interface ASNavigationController : UINavigationController <ASManagesChildVisibilityDepth>
|
||||
|
||||
@end
|
||||
93
AsyncDisplayKit/ASNavigationController.m
Normal file
93
AsyncDisplayKit/ASNavigationController.m
Normal file
@ -0,0 +1,93 @@
|
||||
//
|
||||
// ASNavigationController.m
|
||||
// Pods
|
||||
//
|
||||
// Created by Garrett Moon on 4/27/16.
|
||||
//
|
||||
//
|
||||
|
||||
#import "ASNavigationController.h"
|
||||
|
||||
@implementation ASNavigationController
|
||||
{
|
||||
BOOL _parentManagesVisibilityDepth;
|
||||
NSInteger _visibilityDepth;
|
||||
}
|
||||
|
||||
ASVisibilityDidMoveToParentViewController;
|
||||
|
||||
ASVisibilityViewWillAppear;
|
||||
|
||||
ASVisibilityViewDidDisappearImplementation;
|
||||
|
||||
ASVisibilitySetVisibilityDepth;
|
||||
|
||||
ASVisibilityDepthImplementation;
|
||||
|
||||
- (void)visibilityDepthDidChange
|
||||
{
|
||||
for (UIViewController *viewController in self.viewControllers) {
|
||||
if ([viewController conformsToProtocol:@protocol(ASVisibilityDepth)]) {
|
||||
[(id <ASVisibilityDepth>)viewController visibilityDepthDidChange];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)visibilityDepthOfChildViewController:(UIViewController *)childViewController
|
||||
{
|
||||
NSUInteger viewControllerIndex = [self.viewControllers indexOfObject:childViewController];
|
||||
NSAssert(viewControllerIndex != NSNotFound, @"childViewController is not in the navigation stack.");
|
||||
|
||||
if (viewControllerIndex == self.viewControllers.count - 1) {
|
||||
//view controller is at the top, just return our own visibility depth.
|
||||
return [self visibilityDepth];
|
||||
} else if (viewControllerIndex == 0) {
|
||||
//view controller is the root view controller. Can be accessed by holding the back button.
|
||||
return [self visibilityDepth] + 1;
|
||||
}
|
||||
|
||||
return [self visibilityDepth] + self.viewControllers.count - 1 - viewControllerIndex;
|
||||
}
|
||||
|
||||
#pragma mark - UIKit overrides
|
||||
|
||||
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
|
||||
{
|
||||
NSArray *viewControllers = [super popToViewController:viewController animated:animated];
|
||||
[self visibilityDepthDidChange];
|
||||
return viewControllers;
|
||||
}
|
||||
|
||||
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated
|
||||
{
|
||||
NSArray *viewControllers = [super popToRootViewControllerAnimated:animated];
|
||||
[self visibilityDepthDidChange];
|
||||
return viewControllers;
|
||||
}
|
||||
|
||||
- (void)setViewControllers:(NSArray *)viewControllers
|
||||
{
|
||||
[super setViewControllers:viewControllers];
|
||||
[self visibilityDepthDidChange];
|
||||
}
|
||||
|
||||
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated
|
||||
{
|
||||
[super setViewControllers:viewControllers animated:animated];
|
||||
[self visibilityDepthDidChange];
|
||||
}
|
||||
|
||||
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
|
||||
{
|
||||
[super pushViewController:viewController animated:animated];
|
||||
[self visibilityDepthDidChange];
|
||||
}
|
||||
|
||||
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
|
||||
{
|
||||
UIViewController *viewController = [super popViewControllerAnimated:animated];
|
||||
[self visibilityDepthDidChange];
|
||||
return viewController;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -73,6 +73,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@property (nonatomic, assign, readwrite) BOOL shouldCacheImage;
|
||||
|
||||
/**
|
||||
* If the downloader implements progressive image rendering and this value is YES progressive renders of the
|
||||
* image will be displayed as the image downloads. Regardless of this properties value, progress renders will
|
||||
* only occur when the node is visible. Defaults to YES.
|
||||
*/
|
||||
@property (nonatomic, assign, readwrite) BOOL shouldRenderProgressImages;
|
||||
|
||||
/**
|
||||
* The image quality of the current image. This is a number between 0 and 1 and can be used to track
|
||||
* progressive progress. Calculated by dividing number of bytes / expected number of total bytes.
|
||||
|
||||
@ -46,6 +46,8 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
BOOL _delegateSupportsDidFailWithError;
|
||||
BOOL _delegateSupportsImageNodeDidFinishDecoding;
|
||||
|
||||
BOOL _shouldRenderProgressImages;
|
||||
|
||||
//set on init only
|
||||
BOOL _downloaderSupportsNewProtocol;
|
||||
BOOL _downloaderImplementsSetProgress;
|
||||
@ -83,6 +85,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
_cacheSupportsSynchronousFetch = [cache respondsToSelector:@selector(synchronouslyFetchedCachedImageWithURL:)];
|
||||
|
||||
_shouldCacheImage = YES;
|
||||
_shouldRenderProgressImages = YES;
|
||||
self.shouldBypassEnsureDisplay = YES;
|
||||
|
||||
return self;
|
||||
@ -218,6 +221,26 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
- (void)setShouldRenderProgressImages:(BOOL)shouldRenderProgressImages
|
||||
{
|
||||
ASDN::MutexLocker l(_lock);
|
||||
if (shouldRenderProgressImages == _shouldRenderProgressImages) {
|
||||
return;
|
||||
}
|
||||
|
||||
_shouldRenderProgressImages = shouldRenderProgressImages;
|
||||
|
||||
|
||||
ASDN::MutexUnlocker u(_lock);
|
||||
[self _updateProgressImageBlockOnDownloaderIfNeeded];
|
||||
}
|
||||
|
||||
- (BOOL)shouldRenderProgressImages
|
||||
{
|
||||
ASDN::MutexLocker l(_lock);
|
||||
return _shouldRenderProgressImages;
|
||||
}
|
||||
|
||||
- (BOOL)placeholderShouldPersist
|
||||
{
|
||||
ASDN::MutexLocker l(_lock);
|
||||
@ -309,6 +332,8 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
*/
|
||||
- (void)_updateProgressImageBlockOnDownloaderIfNeeded
|
||||
{
|
||||
BOOL shouldRenderProgressImages = self.shouldRenderProgressImages;
|
||||
|
||||
// Read our interface state before locking so that we don't lock super while holding our lock.
|
||||
ASInterfaceState interfaceState = self.interfaceState;
|
||||
ASDN::MutexLocker l(_lock);
|
||||
@ -318,7 +343,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
}
|
||||
|
||||
ASImageDownloaderProgressImage progress = nil;
|
||||
if (ASInterfaceStateIncludesVisible(interfaceState)) {
|
||||
if (shouldRenderProgressImages && ASInterfaceStateIncludesVisible(interfaceState)) {
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
progress = ^(UIImage * _Nonnull progressImage, CGFloat progress, id _Nullable downloadIdentifier) {
|
||||
__typeof__(self) strongSelf = weakSelf;
|
||||
|
||||
@ -11,7 +11,8 @@
|
||||
@class ASPagerNode;
|
||||
@class ASPagerFlowLayout;
|
||||
|
||||
@protocol ASPagerNodeDataSource <NSObject>
|
||||
#define ASPagerNodeDataSource ASPagerDataSource
|
||||
@protocol ASPagerDataSource <NSObject>
|
||||
|
||||
/**
|
||||
* This method replaces -collectionView:numberOfItemsInSection:
|
||||
@ -65,25 +66,30 @@
|
||||
|
||||
@end
|
||||
|
||||
@protocol ASPagerDelegate <ASCollectionDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@interface ASPagerNode : ASCollectionNode
|
||||
|
||||
// Configures a default horizontal, paging flow layout with 0 inter-item spacing.
|
||||
/// Configures a default horizontal, paging flow layout with 0 inter-item spacing.
|
||||
- (instancetype)init;
|
||||
|
||||
// Initializer with custom-configured flow layout properties.
|
||||
/// Initializer with custom-configured flow layout properties.
|
||||
- (instancetype)initWithCollectionViewLayout:(ASPagerFlowLayout *)flowLayout;
|
||||
|
||||
// Data Source is required, and uses a different protocol from ASCollectionNode.
|
||||
- (void)setDataSource:(id <ASPagerNodeDataSource>)dataSource;
|
||||
- (id <ASPagerNodeDataSource>)dataSource;
|
||||
/// Data Source is required, and uses a different protocol from ASCollectionNode.
|
||||
- (void)setDataSource:(id <ASPagerDataSource>)dataSource;
|
||||
- (id <ASPagerDataSource>)dataSource;
|
||||
|
||||
// Delegate is optional, and uses the same protocol as ASCollectionNode.
|
||||
// This includes UIScrollViewDelegate as well as most methods from UICollectionViewDelegate, like willDisplay...
|
||||
@property (nonatomic, weak) id <ASCollectionDelegate> delegate;
|
||||
@property (nonatomic, weak) id <ASPagerDelegate> delegate;
|
||||
|
||||
// The underlying ASCollectionView object.
|
||||
/// The underlying ASCollectionView object.
|
||||
@property (nonatomic, readonly) ASCollectionView *view;
|
||||
|
||||
/// Scroll the contents of the receiver to ensure that the page is visible.
|
||||
- (void)scrollToPageAtIndex:(NSInteger)index animated:(BOOL)animated;
|
||||
|
||||
@end
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
{
|
||||
ASPagerFlowLayout *_flowLayout;
|
||||
ASPagerNodeProxy *_proxy;
|
||||
__weak id <ASPagerNodeDataSource> _pagerDataSource;
|
||||
__weak id <ASPagerDataSource> _pagerDataSource;
|
||||
BOOL _pagerDataSourceImplementsNodeBlockAtIndex;
|
||||
BOOL _pagerDataSourceImplementsConstrainedSizeForNode;
|
||||
}
|
||||
@ -111,12 +111,12 @@
|
||||
|
||||
#pragma mark - Data Source Proxy
|
||||
|
||||
- (id <ASPagerNodeDataSource>)dataSource
|
||||
- (id <ASPagerDataSource>)dataSource
|
||||
{
|
||||
return _pagerDataSource;
|
||||
}
|
||||
|
||||
- (void)setDataSource:(id <ASPagerNodeDataSource>)pagerDataSource
|
||||
- (void)setDataSource:(id <ASPagerDataSource>)pagerDataSource
|
||||
{
|
||||
if (pagerDataSource != _pagerDataSource) {
|
||||
_pagerDataSource = pagerDataSource;
|
||||
|
||||
15
AsyncDisplayKit/ASTabBarController.h
Normal file
15
AsyncDisplayKit/ASTabBarController.h
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// ASTabBarController.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Garrett Moon on 5/10/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "ASVisibilityProtocols.h"
|
||||
|
||||
@interface ASTabBarController : UITabBarController <ASManagesChildVisibilityDepth>
|
||||
|
||||
@end
|
||||
70
AsyncDisplayKit/ASTabBarController.m
Normal file
70
AsyncDisplayKit/ASTabBarController.m
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// ASTabBarController.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Garrett Moon on 5/10/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASTabBarController.h"
|
||||
|
||||
@implementation ASTabBarController
|
||||
{
|
||||
BOOL _parentManagesVisibilityDepth;
|
||||
NSInteger _visibilityDepth;
|
||||
}
|
||||
|
||||
ASVisibilityDidMoveToParentViewController;
|
||||
|
||||
ASVisibilityViewWillAppear;
|
||||
|
||||
ASVisibilityViewDidDisappearImplementation;
|
||||
|
||||
ASVisibilitySetVisibilityDepth;
|
||||
|
||||
ASVisibilityDepthImplementation;
|
||||
|
||||
- (void)visibilityDepthDidChange
|
||||
{
|
||||
for (UIViewController *viewController in self.viewControllers) {
|
||||
if ([viewController conformsToProtocol:@protocol(ASVisibilityDepth)]) {
|
||||
[(id <ASVisibilityDepth>)viewController visibilityDepthDidChange];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)visibilityDepthOfChildViewController:(UIViewController *)childViewController
|
||||
{
|
||||
if (self.selectedViewController == childViewController) {
|
||||
return [self visibilityDepth];
|
||||
}
|
||||
return [self visibilityDepth] + 1;
|
||||
}
|
||||
|
||||
#pragma mark - UIKit overrides
|
||||
|
||||
- (void)setViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers
|
||||
{
|
||||
[super setViewControllers:viewControllers];
|
||||
[self visibilityDepthDidChange];
|
||||
}
|
||||
|
||||
- (void)setViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers animated:(BOOL)animated
|
||||
{
|
||||
[super setViewControllers:viewControllers animated:animated];
|
||||
[self visibilityDepthDidChange];
|
||||
}
|
||||
|
||||
- (void)setSelectedIndex:(NSUInteger)selectedIndex
|
||||
{
|
||||
[super setSelectedIndex:selectedIndex];
|
||||
[self visibilityDepthDidChange];
|
||||
}
|
||||
|
||||
- (void)setSelectedViewController:(__kindof UIViewController *)selectedViewController
|
||||
{
|
||||
[super setSelectedViewController:selectedViewController];
|
||||
[self visibilityDepthDidChange];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -6,6 +6,7 @@
|
||||
// Copyright © 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASFlowLayoutController.h"
|
||||
#import "ASTableViewInternal.h"
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
@ -20,6 +21,10 @@
|
||||
@end
|
||||
|
||||
@interface ASTableNode ()
|
||||
{
|
||||
ASDN::RecursiveMutex _environmentStateLock;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) _ASTablePendingState *pendingState;
|
||||
@end
|
||||
|
||||
@ -158,4 +163,6 @@
|
||||
[self.view clearFetchedData];
|
||||
}
|
||||
|
||||
ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock)
|
||||
|
||||
@end
|
||||
@ -16,6 +16,7 @@
|
||||
#import "ASDisplayNodeExtras.h"
|
||||
#import "ASDisplayNode+Beta.h"
|
||||
#import "ASDisplayNode+FrameworkPrivate.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASLayout.h"
|
||||
#import "ASLayoutController.h"
|
||||
@ -88,7 +89,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
- (instancetype)_initWithTableView:(ASTableView *)tableView;
|
||||
@end
|
||||
|
||||
@interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView>
|
||||
@interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView, ASDataControllerEnvironmentDelegate>
|
||||
{
|
||||
ASTableViewProxy *_proxyDataSource;
|
||||
ASTableViewProxy *_proxyDelegate;
|
||||
@ -175,6 +176,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
_dataController = [[dataControllerClass alloc] initWithAsyncDataFetching:NO];
|
||||
_dataController.dataSource = self;
|
||||
_dataController.delegate = _rangeController;
|
||||
_dataController.environmentDelegate = self;
|
||||
|
||||
_layoutController.dataSource = _dataController;
|
||||
|
||||
@ -268,10 +270,9 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
{
|
||||
// Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle
|
||||
// the (common) case of nilling the asyncDataSource in the ViewController's dealloc. In this case our _asyncDataSource
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to nil out
|
||||
// super.dataSource in this case because calls to ASTableViewProxy will start failing and cause crashes.
|
||||
|
||||
super.dataSource = nil;
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
|
||||
// reference to the old dataSource in this case because calls to ASTableViewProxy will start failing and cause crashes.
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id oldDataSource = self.dataSource;
|
||||
|
||||
if (asyncDataSource == nil) {
|
||||
_asyncDataSource = nil;
|
||||
@ -299,13 +300,9 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
{
|
||||
// Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle
|
||||
// the (common) case of nilling the asyncDelegate in the ViewController's dealloc. In this case our _asyncDelegate
|
||||
// will return as nil (ARC magic) even though the _proxyDelegate still exists. It's really important to nil out
|
||||
// super.delegate in this case because calls to ASTableViewProxy will start failing and cause crashes.
|
||||
|
||||
// Order is important here, the asyncDelegate must be callable while nilling super.delegate to avoid random crashes
|
||||
// in UIScrollViewAccessibility.
|
||||
|
||||
super.delegate = nil;
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
|
||||
// reference to the old delegate in this case because calls to ASTableViewProxy will start failing and cause crashes.
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id oldDelegate = super.delegate;
|
||||
|
||||
if (asyncDelegate == nil) {
|
||||
_asyncDelegate = nil;
|
||||
@ -1083,6 +1080,16 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - ASDataControllerEnvironmentDelegate
|
||||
|
||||
- (id<ASEnvironment>)dataControllerEnvironment
|
||||
{
|
||||
if (self.tableNode) {
|
||||
return self.tableNode;
|
||||
}
|
||||
return self.strongTableNode;
|
||||
}
|
||||
|
||||
#pragma mark - _ASTableViewCellDelegate
|
||||
|
||||
- (void)didLayoutSubviewsOfTableViewCell:(_ASTableViewCell *)tableViewCell
|
||||
|
||||
@ -34,19 +34,19 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
|
||||
@interface ASTextNode : ASControlNode
|
||||
|
||||
/**
|
||||
@abstract The attributed string to show.
|
||||
@abstract The styled text displayed by the node.
|
||||
@discussion Defaults to nil, no text is shown.
|
||||
For inline image attachments, add an attribute of key NSAttachmentAttributeName, with a value of an NSTextAttachment.
|
||||
*/
|
||||
@property (nullable, nonatomic, copy) NSAttributedString *attributedString;
|
||||
@property (nullable, nonatomic, copy) NSAttributedString *attributedText;
|
||||
|
||||
#pragma mark - Truncation
|
||||
|
||||
/**
|
||||
@abstract The attributedString to use when the text must be truncated.
|
||||
@abstract The attributedText to use when the text must be truncated.
|
||||
@discussion Defaults to a localized ellipsis character.
|
||||
*/
|
||||
@property (nullable, nonatomic, copy) NSAttributedString *truncationAttributedString;
|
||||
@property (nullable, nonatomic, copy) NSAttributedString *truncationAttributedText;
|
||||
|
||||
/**
|
||||
@summary The second attributed string appended for truncation.
|
||||
@ -270,4 +270,28 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* @abstract Text node deprecated properties
|
||||
*/
|
||||
@interface ASTextNode (Deprecated)
|
||||
|
||||
/**
|
||||
The attributedString and attributedText properties are equivalent, but attributedText is now the standard API
|
||||
name in order to match UILabel and ASEditableTextNode.
|
||||
|
||||
@see attributedText
|
||||
*/
|
||||
@property (nullable, nonatomic, copy) NSAttributedString *attributedString;
|
||||
|
||||
|
||||
/**
|
||||
The truncationAttributedString and truncationAttributedText properties are equivalent, but attributedText is now the
|
||||
standard API name in order to match UILabel and ASEditableTextNode.
|
||||
|
||||
@see truncationAttributedText
|
||||
*/
|
||||
@property (nullable, nonatomic, copy) NSAttributedString *truncationAttributedString;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -67,7 +67,7 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
|
||||
|
||||
NSArray *_exclusionPaths;
|
||||
|
||||
NSAttributedString *_composedTruncationString;
|
||||
NSAttributedString *_composedTruncationText;
|
||||
|
||||
NSString *_highlightedLinkAttributeName;
|
||||
id _highlightedLinkAttributeValue;
|
||||
@ -105,7 +105,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
self.needsDisplayOnBoundsChange = YES;
|
||||
|
||||
_truncationMode = NSLineBreakByWordWrapping;
|
||||
_composedTruncationString = DefaultTruncationAttributedString();
|
||||
_composedTruncationText = DefaultTruncationAttributedString();
|
||||
|
||||
// The common case is for a text node to be non-opaque and blended over some background.
|
||||
self.opaque = NO;
|
||||
@ -158,8 +158,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
NSString *plainString = [[_attributedString string] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||
NSString *truncationString = [_composedTruncationString string];
|
||||
NSString *plainString = [[_attributedText string] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||
NSString *truncationString = [_composedTruncationText string];
|
||||
if (plainString.length > 50)
|
||||
plainString = [[plainString substringToIndex:50] stringByAppendingString:@"\u2026"];
|
||||
return [NSString stringWithFormat:@"<%@: %p; text = \"%@\"; truncation string = \"%@\"; frame = %@; renderer = %p>", self.class, self, plainString, truncationString, self.nodeLoaded ? NSStringFromCGRect(self.layer.frame) : nil, _renderer];
|
||||
@ -237,8 +237,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
- (ASTextKitAttributes)_rendererAttributes
|
||||
{
|
||||
return {
|
||||
.attributedString = _attributedString,
|
||||
.truncationAttributedString = _composedTruncationString,
|
||||
.attributedString = _attributedText,
|
||||
.truncationAttributedString = _composedTruncationText,
|
||||
.lineBreakMode = _truncationMode,
|
||||
.maximumNumberOfLines = _maximumNumberOfLines,
|
||||
.exclusionPaths = _exclusionPaths,
|
||||
@ -340,10 +340,10 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
[self setNeedsDisplay];
|
||||
|
||||
CGSize size = [[self _renderer] size];
|
||||
if (self.attributedString.length > 0) {
|
||||
if (_attributedText.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;
|
||||
self.ascender = round([[_attributedText attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale;
|
||||
self.descender = round([[_attributedText attribute:NSFontAttributeName atIndex:_attributedText.length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale;
|
||||
if (_renderer.currentScaleFactor > 0 && _renderer.currentScaleFactor < 1.0) {
|
||||
// while not perfect, this is a good estimate of what the ascender of the scaled font will be.
|
||||
self.ascender *= _renderer.currentScaleFactor;
|
||||
@ -355,28 +355,28 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
|
||||
#pragma mark - Modifying User Text
|
||||
|
||||
- (void)setAttributedString:(NSAttributedString *)attributedString
|
||||
- (void)setAttributedText:(NSAttributedString *)attributedText
|
||||
{
|
||||
if (attributedString == nil) {
|
||||
attributedString = [[NSAttributedString alloc] initWithString:@"" attributes:nil];
|
||||
if (attributedText == nil) {
|
||||
attributedText = [[NSAttributedString alloc] initWithString:@"" attributes:nil];
|
||||
}
|
||||
|
||||
if (ASObjectIsEqual(attributedString, _attributedString)) {
|
||||
if (ASObjectIsEqual(attributedText, _attributedText)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_attributedString = ASCleanseAttributedStringOfCoreTextAttributes(attributedString);
|
||||
_attributedText = ASCleanseAttributedStringOfCoreTextAttributes(attributedText);
|
||||
|
||||
if (_attributedString.length > 0) {
|
||||
if (_attributedText.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;
|
||||
self.ascender = round([[_attributedText attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale;
|
||||
self.descender = round([[_attributedText attribute:NSFontAttributeName atIndex:_attributedText.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
|
||||
// not take into account the attributes of attributedString in the last line
|
||||
[self _updateComposedTruncationString];
|
||||
// not take into account the attributes of attributedText in the last line
|
||||
[self _updateComposedTruncationText];
|
||||
|
||||
// We need an entirely new renderer
|
||||
[self _invalidateRenderer];
|
||||
@ -386,10 +386,10 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
|
||||
[self setNeedsDisplay];
|
||||
|
||||
self.accessibilityLabel = _attributedString.string;
|
||||
self.accessibilityLabel = _attributedText.string;
|
||||
|
||||
// We're an accessibility element by default if there is a string.
|
||||
self.isAccessibilityElement = _attributedString.length != 0;
|
||||
self.isAccessibilityElement = _attributedText.length != 0;
|
||||
}
|
||||
|
||||
#pragma mark - Text Layout
|
||||
@ -470,7 +470,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
{
|
||||
ASTextKitRenderer *renderer = [self _renderer];
|
||||
NSRange visibleRange = renderer.visibleRanges[0];
|
||||
NSAttributedString *attributedString = _attributedString;
|
||||
NSAttributedString *attributedString = _attributedText;
|
||||
NSRange clampedRange = NSIntersectionRange(visibleRange, NSMakeRange(0, attributedString.length));
|
||||
|
||||
// Check in a 9-point region around the actual touch point so we make sure
|
||||
@ -1023,14 +1023,14 @@ static NSAttributedString *DefaultTruncationAttributedString()
|
||||
return defaultTruncationAttributedString;
|
||||
}
|
||||
|
||||
- (void)setTruncationAttributedString:(NSAttributedString *)truncationAttributedString
|
||||
- (void)setTruncationAttributedText:(NSAttributedString *)truncationAttributedText
|
||||
{
|
||||
if (ASObjectIsEqual(_truncationAttributedString, truncationAttributedString)) {
|
||||
if (ASObjectIsEqual(_truncationAttributedText, truncationAttributedText)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_truncationAttributedString = [truncationAttributedString copy];
|
||||
[self _invalidateTruncationString];
|
||||
_truncationAttributedText = [truncationAttributedText copy];
|
||||
[self _invalidateTruncationText];
|
||||
}
|
||||
|
||||
- (void)setAdditionalTruncationMessage:(NSAttributedString *)additionalTruncationMessage
|
||||
@ -1040,7 +1040,7 @@ static NSAttributedString *DefaultTruncationAttributedString()
|
||||
}
|
||||
|
||||
_additionalTruncationMessage = [additionalTruncationMessage copy];
|
||||
[self _invalidateTruncationString];
|
||||
[self _invalidateTruncationText];
|
||||
}
|
||||
|
||||
- (void)setTruncationMode:(NSLineBreakMode)truncationMode
|
||||
@ -1055,7 +1055,7 @@ static NSAttributedString *DefaultTruncationAttributedString()
|
||||
- (BOOL)isTruncated
|
||||
{
|
||||
NSRange visibleRange = [self _renderer].visibleRanges[0];
|
||||
return visibleRange.length < _attributedString.length;
|
||||
return visibleRange.length < _attributedText.length;
|
||||
}
|
||||
|
||||
- (void)setPointSizeScaleFactors:(NSArray *)pointSizeScaleFactors
|
||||
@ -1082,14 +1082,14 @@ static NSAttributedString *DefaultTruncationAttributedString()
|
||||
|
||||
#pragma mark - Truncation Message
|
||||
|
||||
- (void)_updateComposedTruncationString
|
||||
- (void)_updateComposedTruncationText
|
||||
{
|
||||
_composedTruncationString = [self _prepareTruncationStringForDrawing:[self _composedTruncationString]];
|
||||
_composedTruncationText = [self _prepareTruncationStringForDrawing:[self _composedTruncationText]];
|
||||
}
|
||||
|
||||
- (void)_invalidateTruncationString
|
||||
- (void)_invalidateTruncationText
|
||||
{
|
||||
[self _updateComposedTruncationString];
|
||||
[self _updateComposedTruncationText];
|
||||
[self _invalidateRenderer];
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
@ -1111,7 +1111,7 @@ static NSAttributedString *DefaultTruncationAttributedString()
|
||||
NSUInteger additionalTruncationMessageLength = _additionalTruncationMessage.length;
|
||||
// We get the location of the truncation token, then add the length of the
|
||||
// truncation attributed string +1 for the space between.
|
||||
NSRange range = NSMakeRange(truncationTokenIndex + _truncationAttributedString.length + 1, additionalTruncationMessageLength);
|
||||
NSRange range = NSMakeRange(truncationTokenIndex + _truncationAttributedText.length + 1, additionalTruncationMessageLength);
|
||||
return range;
|
||||
}
|
||||
|
||||
@ -1120,24 +1120,24 @@ static NSAttributedString *DefaultTruncationAttributedString()
|
||||
* additional truncation message and a truncation attributed string, they will
|
||||
* be properly composed.
|
||||
*/
|
||||
- (NSAttributedString *)_composedTruncationString
|
||||
- (NSAttributedString *)_composedTruncationText
|
||||
{
|
||||
//If we have neither return the default
|
||||
if (!_additionalTruncationMessage && !_truncationAttributedString) {
|
||||
return _composedTruncationString;
|
||||
if (!_additionalTruncationMessage && !_truncationAttributedText) {
|
||||
return _composedTruncationText;
|
||||
}
|
||||
// Short circuit if we only have one or the other.
|
||||
if (!_additionalTruncationMessage) {
|
||||
return _truncationAttributedString;
|
||||
return _truncationAttributedText;
|
||||
}
|
||||
if (!_truncationAttributedString) {
|
||||
if (!_truncationAttributedText) {
|
||||
return _additionalTruncationMessage;
|
||||
}
|
||||
|
||||
// If we've reached this point, both _additionalTruncationMessage and
|
||||
// _truncationAttributedString are present. Compose them.
|
||||
|
||||
NSMutableAttributedString *newComposedTruncationString = [[NSMutableAttributedString alloc] initWithAttributedString:_truncationAttributedString];
|
||||
NSMutableAttributedString *newComposedTruncationString = [[NSMutableAttributedString alloc] initWithAttributedString:_truncationAttributedText];
|
||||
[newComposedTruncationString replaceCharactersInRange:NSMakeRange(newComposedTruncationString.length, 0) withString:@" "];
|
||||
[newComposedTruncationString appendAttributedString:_additionalTruncationMessage];
|
||||
return newComposedTruncationString;
|
||||
@ -1153,9 +1153,9 @@ static NSAttributedString *DefaultTruncationAttributedString()
|
||||
truncationString = ASCleanseAttributedStringOfCoreTextAttributes(truncationString);
|
||||
NSMutableAttributedString *truncationMutableString = [truncationString mutableCopy];
|
||||
// Grab the attributes from the full string
|
||||
if (_attributedString.length > 0) {
|
||||
NSAttributedString *originalString = _attributedString;
|
||||
NSInteger originalStringLength = _attributedString.length;
|
||||
if (_attributedText.length > 0) {
|
||||
NSAttributedString *originalString = _truncationAttributedText;
|
||||
NSInteger originalStringLength = _truncationAttributedText.length;
|
||||
// Add any of the original string's attributes to the truncation string,
|
||||
// but don't overwrite any of the truncation string's attributes
|
||||
NSDictionary *originalStringAttributes = [originalString attributesAtIndex:originalStringLength-1 effectiveRange:NULL];
|
||||
@ -1170,3 +1170,27 @@ static NSAttributedString *DefaultTruncationAttributedString()
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASTextNode (Deprecated)
|
||||
|
||||
- (void)setAttributedString:(NSAttributedString *)attributedString
|
||||
{
|
||||
self.attributedText = attributedString;
|
||||
}
|
||||
|
||||
- (NSAttributedString *)attributedString
|
||||
{
|
||||
return self.attributedText;
|
||||
}
|
||||
|
||||
- (void)setTruncationAttributedString:(NSAttributedString *)truncationAttributedString
|
||||
{
|
||||
self.truncationAttributedText = truncationAttributedString;
|
||||
}
|
||||
|
||||
- (NSAttributedString *)truncationAttributedString
|
||||
{
|
||||
return self.truncationAttributedText;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -64,9 +64,9 @@ static NSString * const kStatus = @"status";
|
||||
|
||||
ASImageNode *_placeholderImageNode; // TODO: Make ASVideoNode an ASImageNode subclass; remove this.
|
||||
|
||||
ASButtonNode *_playButton;
|
||||
ASButtonNode *_playButtonNode;
|
||||
ASDisplayNode *_playerNode;
|
||||
ASDisplayNode *_spinner;
|
||||
ASDisplayNode *_spinnerNode;
|
||||
NSString *_gravity;
|
||||
}
|
||||
|
||||
@ -185,6 +185,45 @@ static NSString * const kStatus = @"status";
|
||||
[notificationCenter removeObserver:self name:AVPlayerItemNewErrorLogEntryNotification object:playerItem];
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
// All subnodes should taking the whole node frame
|
||||
CGSize maxSize = constrainedSize.max;
|
||||
if (!CGSizeEqualToSize(self.preferredFrameSize, CGSizeZero)) {
|
||||
maxSize = self.preferredFrameSize;
|
||||
}
|
||||
|
||||
// Prevent crashes through if infinite width or height
|
||||
if (isinf(maxSize.width) || isinf(maxSize.height)) {
|
||||
ASDisplayNodeAssert(NO, @"Infinite width or height in ASVideoNode");
|
||||
maxSize = CGSizeZero;
|
||||
}
|
||||
|
||||
// Stretch out play button, placeholder image player node to the max size
|
||||
NSMutableArray *children = [NSMutableArray array];
|
||||
if (_playButtonNode) {
|
||||
_playButtonNode.preferredFrameSize = maxSize;
|
||||
[children addObject:_playButtonNode];
|
||||
}
|
||||
if (_placeholderImageNode) {
|
||||
_placeholderImageNode.preferredFrameSize = maxSize;
|
||||
[children addObject:_placeholderImageNode];
|
||||
}
|
||||
if (_playerNode) {
|
||||
_playerNode.preferredFrameSize = maxSize;
|
||||
[children addObject:_playerNode];
|
||||
}
|
||||
|
||||
// Center spinner node
|
||||
if (_spinnerNode) {
|
||||
ASCenterLayoutSpec *centerLayoutSpec = [ASCenterLayoutSpec centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringXY sizingOptions:ASCenterLayoutSpecSizingOptionDefault child:_spinnerNode];
|
||||
centerLayoutSpec.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(maxSize);
|
||||
[children addObject:centerLayoutSpec];
|
||||
}
|
||||
|
||||
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:children];
|
||||
}
|
||||
|
||||
- (void)layout
|
||||
{
|
||||
[super layout];
|
||||
@ -192,17 +231,9 @@ static NSString * const kStatus = @"status";
|
||||
CGRect bounds = self.bounds;
|
||||
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
_placeholderImageNode.frame = bounds;
|
||||
_playerNode.frame = bounds;
|
||||
_playButton.frame = bounds;
|
||||
|
||||
CGFloat horizontalDiff = (bounds.size.width - _playButton.bounds.size.width)/2;
|
||||
CGFloat verticalDiff = (bounds.size.height - _playButton.bounds.size.height)/2;
|
||||
_playButton.hitTestSlop = UIEdgeInsetsMake(-verticalDiff, -horizontalDiff, -verticalDiff, -horizontalDiff);
|
||||
|
||||
_spinner.bounds = CGRectMake(0, 0, 44, 44);
|
||||
_spinner.position = CGPointMake(bounds.size.width/2, bounds.size.height/2);
|
||||
CGFloat horizontalDiff = (CGRectGetWidth(bounds) - CGRectGetWidth(_playButtonNode.bounds))/2;
|
||||
CGFloat verticalDiff = (CGRectGetHeight(bounds) - CGRectGetHeight(_playButtonNode.bounds))/2;
|
||||
_playButtonNode.hitTestSlop = UIEdgeInsetsMake(-verticalDiff, -horizontalDiff, -verticalDiff, -horizontalDiff);
|
||||
}
|
||||
|
||||
- (void)generatePlaceholderImage
|
||||
@ -370,6 +401,7 @@ static NSString * const kStatus = @"status";
|
||||
|
||||
|
||||
#pragma mark - Video Properties
|
||||
|
||||
- (void)setPlayerState:(ASVideoNodePlayerState)playerState
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
@ -385,28 +417,26 @@ static NSString * const kStatus = @"status";
|
||||
}
|
||||
|
||||
_playerState = playerState;
|
||||
|
||||
}
|
||||
|
||||
- (void)setPlayButton:(ASButtonNode *)playButton
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
[_playButton removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
[_playButton removeFromSupernode];
|
||||
[_playButtonNode removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
[_playButtonNode removeFromSupernode];
|
||||
|
||||
_playButton = playButton;
|
||||
_playButtonNode = playButton;
|
||||
[_playButtonNode addTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
|
||||
[self addSubnode:playButton];
|
||||
|
||||
[_playButton addTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (ASButtonNode *)playButton
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
return _playButton;
|
||||
return _playButtonNode;
|
||||
}
|
||||
|
||||
- (void)setAsset:(AVAsset *)asset
|
||||
@ -471,14 +501,12 @@ static NSString * const kStatus = @"status";
|
||||
- (NSString *)gravity
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
return _gravity;
|
||||
}
|
||||
|
||||
- (BOOL)muted
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
return _muted;
|
||||
}
|
||||
|
||||
@ -507,11 +535,13 @@ static NSString * const kStatus = @"status";
|
||||
if (_playerNode == nil) {
|
||||
_playerNode = [self constructPlayerNode];
|
||||
|
||||
if (_playButton.supernode == self) {
|
||||
[self insertSubnode:_playerNode belowSubnode:_playButton];
|
||||
if (_playButtonNode.supernode == self) {
|
||||
[self insertSubnode:_playerNode belowSubnode:_playButtonNode];
|
||||
} else {
|
||||
[self addSubnode:_playerNode];
|
||||
}
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
|
||||
@ -519,7 +549,7 @@ static NSString * const kStatus = @"status";
|
||||
_shouldBePlaying = YES;
|
||||
|
||||
[UIView animateWithDuration:0.15 animations:^{
|
||||
_playButton.alpha = 0.0;
|
||||
_playButtonNode.alpha = 0.0;
|
||||
}];
|
||||
if (![self ready]) {
|
||||
[self showSpinner];
|
||||
@ -538,28 +568,29 @@ static NSString * const kStatus = @"status";
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
if (!_spinner) {
|
||||
_spinner = [[ASDisplayNode alloc] initWithViewBlock:^UIView *{
|
||||
if (!_spinnerNode) {
|
||||
_spinnerNode = [[ASDisplayNode alloc] initWithViewBlock:^UIView *{
|
||||
UIActivityIndicatorView *spinnnerView = [[UIActivityIndicatorView alloc] init];
|
||||
spinnnerView.color = [UIColor whiteColor];
|
||||
|
||||
return spinnnerView;
|
||||
}];
|
||||
_spinnerNode.preferredFrameSize = CGSizeMake(44.0, 44.0);
|
||||
|
||||
[self addSubnode:_spinner];
|
||||
[self addSubnode:_spinnerNode];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
[(UIActivityIndicatorView *)_spinner.view startAnimating];
|
||||
[(UIActivityIndicatorView *)_spinnerNode.view startAnimating];
|
||||
}
|
||||
|
||||
- (void)removeSpinner
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
if (!_spinner) {
|
||||
if (!_spinnerNode) {
|
||||
return;
|
||||
}
|
||||
[_spinner removeFromSupernode];
|
||||
_spinner = nil;
|
||||
[_spinnerNode removeFromSupernode];
|
||||
_spinnerNode = nil;
|
||||
}
|
||||
|
||||
- (void)pause
|
||||
@ -573,7 +604,7 @@ static NSString * const kStatus = @"status";
|
||||
[self removeSpinner];
|
||||
_shouldBePlaying = NO;
|
||||
[UIView animateWithDuration:0.15 animations:^{
|
||||
_playButton.alpha = 1.0;
|
||||
_playButtonNode.alpha = 1.0;
|
||||
}];
|
||||
}
|
||||
|
||||
@ -634,7 +665,7 @@ static NSString * const kStatus = @"status";
|
||||
- (ASDisplayNode *)spinner
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
return _spinner;
|
||||
return _spinnerNode;
|
||||
}
|
||||
|
||||
- (ASImageNode *)placeholderImageNode
|
||||
@ -670,6 +701,8 @@ static NSString * const kStatus = @"status";
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
_playerNode = playerNode;
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setPlayer:(AVPlayer *)player
|
||||
@ -698,7 +731,7 @@ static NSString * const kStatus = @"status";
|
||||
{
|
||||
[_player removeTimeObserver:_timeObserver];
|
||||
_timeObserver = nil;
|
||||
[_playButton removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
[_playButtonNode removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
[self removePlayerItemObservers:_currentPlayerItem];
|
||||
}
|
||||
|
||||
|
||||
@ -8,15 +8,43 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <AsyncDisplayKit/ASDisplayNode.h>
|
||||
#import <AsyncDisplayKit/ASVisibilityProtocols.h>
|
||||
|
||||
@class ASTraitCollection;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface ASViewController<__covariant DisplayNodeType : ASDisplayNode *> : UIViewController
|
||||
typedef ASTraitCollection * _Nonnull (^ASDisplayTraitsForTraitCollectionBlock)(UITraitCollection *traitCollection);
|
||||
typedef ASTraitCollection * _Nonnull (^ASDisplayTraitsForTraitWindowSizeBlock)(CGSize windowSize);
|
||||
|
||||
@interface ASViewController<__covariant DisplayNodeType : ASDisplayNode *> : UIViewController <ASVisibilityDepth>
|
||||
|
||||
- (instancetype)initWithNode:(DisplayNodeType)node NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property (nonatomic, strong, readonly) DisplayNodeType node;
|
||||
|
||||
/**
|
||||
* An optional context to pass along with an ASTraitCollection.
|
||||
* This can be used to pass any internal state to all subnodes via the ASTraitCollection that is not
|
||||
* included in UITraitCollection. This could range from more fine-tuned size classes to a class of
|
||||
* constants that is based upon the new trait collection.
|
||||
*
|
||||
* Be aware that internally this context is held by a C struct which cannot retain the pointer. Therefore
|
||||
* ASVC keeps a strong reference to the context to make sure that it stays alive. If you change this value
|
||||
* it will propagate the change to the subnodes.
|
||||
*/
|
||||
@property (nonatomic, strong) id _Nullable traitColectionContext;
|
||||
|
||||
/**
|
||||
* Set this block to customize the ASDisplayTraits returned when the VC transitions to the given traitCollection.
|
||||
*/
|
||||
@property (nonatomic, copy) ASDisplayTraitsForTraitCollectionBlock overrideDisplayTraitsWithTraitCollection;
|
||||
|
||||
/**
|
||||
* Set this block to customize the ASDisplayTraits returned when the VC transitions to the given window size.
|
||||
*/
|
||||
@property (nonatomic, copy) ASDisplayTraitsForTraitWindowSizeBlock overrideDisplayTraitsWithWindowSize;
|
||||
|
||||
/**
|
||||
* @abstract Passthrough property to the the .interfaceState of the node.
|
||||
* @return The current ASInterfaceState of the node, indicating whether it is visible and other situational properties.
|
||||
|
||||
@ -13,10 +13,14 @@
|
||||
#import "ASDisplayNode+Beta.h"
|
||||
#import "ASRangeControllerUpdateRangeProtocol+Beta.h"
|
||||
|
||||
#define AS_LOG_VISIBILITY_CHANGES 0
|
||||
|
||||
@implementation ASViewController
|
||||
{
|
||||
BOOL _ensureDisplayed;
|
||||
BOOL _automaticallyAdjustRangeModeBasedOnViewEvents;
|
||||
BOOL _parentManagesVisibilityDepth;
|
||||
NSInteger _visibilityDepth;
|
||||
}
|
||||
|
||||
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
|
||||
@ -81,6 +85,8 @@
|
||||
[super viewDidLayoutSubviews];
|
||||
}
|
||||
|
||||
ASVisibilityDidMoveToParentViewController;
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
@ -88,14 +94,45 @@
|
||||
[_node measureWithSizeRange:[self nodeConstrainedSize]];
|
||||
[_node recursivelyFetchData];
|
||||
|
||||
[self updateCurrentRangeModeWithModeIfPossible:ASLayoutRangeModeFull];
|
||||
if (_parentManagesVisibilityDepth == NO) {
|
||||
[self setVisibilityDepth:0];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewDidDisappear:animated];
|
||||
ASVisibilitySetVisibilityDepth;
|
||||
|
||||
[self updateCurrentRangeModeWithModeIfPossible:ASLayoutRangeModeMinimum];
|
||||
ASVisibilityViewDidDisappearImplementation;
|
||||
|
||||
ASVisibilityDepthImplementation;
|
||||
|
||||
- (void)visibilityDepthDidChange
|
||||
{
|
||||
ASLayoutRangeMode rangeMode = ASLayoutRangeModeForVisibilityDepth(self.visibilityDepth);
|
||||
#if AS_LOG_VISIBILITY_CHANGES
|
||||
NSString *rangeModeString;
|
||||
switch (rangeMode) {
|
||||
case ASLayoutRangeModeMinimum:
|
||||
rangeModeString = @"Minimum";
|
||||
break;
|
||||
|
||||
case ASLayoutRangeModeFull:
|
||||
rangeModeString = @"Full";
|
||||
break;
|
||||
|
||||
case ASLayoutRangeModeVisibleOnly:
|
||||
rangeModeString = @"Visible Only";
|
||||
break;
|
||||
|
||||
case ASLayoutRangeModeLowMemory:
|
||||
rangeModeString = @"Low Memory";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
NSLog(@"Updating visibility of:%@ to: %@ (visibility depth: %d)", self, rangeModeString, self.visibilityDepth);
|
||||
#endif
|
||||
[self updateCurrentRangeModeWithModeIfPossible:rangeMode];
|
||||
}
|
||||
|
||||
#pragma mark - Automatic range mode
|
||||
@ -113,7 +150,9 @@
|
||||
- (void)updateCurrentRangeModeWithModeIfPossible:(ASLayoutRangeMode)rangeMode
|
||||
{
|
||||
if (!_automaticallyAdjustRangeModeBasedOnViewEvents) { return; }
|
||||
if (![_node conformsToProtocol:@protocol(ASRangeControllerUpdateRangeProtocol)]) { return; }
|
||||
if (![_node conformsToProtocol:@protocol(ASRangeControllerUpdateRangeProtocol)]) {
|
||||
return;
|
||||
}
|
||||
|
||||
id<ASRangeControllerUpdateRangeProtocol> updateRangeNode = (id<ASRangeControllerUpdateRangeProtocol>)_node;
|
||||
[updateRangeNode updateCurrentRangeWithMode:rangeMode];
|
||||
103
AsyncDisplayKit/ASVisibilityProtocols.h
Normal file
103
AsyncDisplayKit/ASVisibilityProtocols.h
Normal file
@ -0,0 +1,103 @@
|
||||
//
|
||||
// ASVisibilityProtocols.h
|
||||
// Pods
|
||||
//
|
||||
// Created by Garrett Moon on 4/27/16.
|
||||
//
|
||||
//
|
||||
|
||||
#import "ASLayoutRangeType.h"
|
||||
|
||||
#import "ASBaseDefines.h"
|
||||
|
||||
@class UIViewController;
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_BEGIN
|
||||
|
||||
extern ASLayoutRangeMode ASLayoutRangeModeForVisibilityDepth(NSUInteger visibilityDepth);
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_END
|
||||
|
||||
@protocol ASVisibilityDepth <NSObject>
|
||||
|
||||
/**
|
||||
* @abstract Represents the number of user actions necessary to reach the view controller. An increased visibility
|
||||
* depth indicates a higher number of user interactions for the view controller to be visible again. For example,
|
||||
* an onscreen navigation controller's top view controller should have a visibility depth of 0. The view controller
|
||||
* one from the top should have a visibility deptch of 1 as should the root view controller in the stack (because
|
||||
* the user can hold the back button to pop to the root view controller).
|
||||
*
|
||||
* Visibility depth is used to automatically adjust ranges on range controllers (and thus free up memory) and can
|
||||
* be used to reduce memory usage of other items as well.
|
||||
*/
|
||||
- (NSInteger)visibilityDepth;
|
||||
|
||||
|
||||
- (void)visibilityDepthDidChange;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* @abstract Container view controllers should adopt this protocol to indicate that they will manage their child's
|
||||
* visibilityDepth. For example, ASNavigationController adopts this protocol and manages its childrens visibility
|
||||
* depth.
|
||||
*
|
||||
* If you adopt this protocol, you *must* also emit visibilityDepthDidChange messages to child view controllers.
|
||||
*
|
||||
* @param childViewController Expected to return the visibility depth of the child view controller.
|
||||
*/
|
||||
@protocol ASManagesChildVisibilityDepth <ASVisibilityDepth>
|
||||
|
||||
- (NSInteger)visibilityDepthOfChildViewController:(UIViewController *)childViewController;
|
||||
|
||||
@end
|
||||
|
||||
#define ASVisibilitySetVisibilityDepth \
|
||||
- (void)setVisibilityDepth:(NSUInteger)visibilityDepth \
|
||||
{ \
|
||||
if (_visibilityDepth == visibilityDepth) { \
|
||||
return; \
|
||||
} \
|
||||
_visibilityDepth = visibilityDepth; \
|
||||
[self visibilityDepthDidChange]; \
|
||||
}
|
||||
|
||||
#define ASVisibilityDepthImplementation \
|
||||
- (NSInteger)visibilityDepth \
|
||||
{ \
|
||||
if (self.parentViewController && _parentManagesVisibilityDepth == NO) { \
|
||||
_parentManagesVisibilityDepth = [self.parentViewController conformsToProtocol:@protocol(ASManagesChildVisibilityDepth)]; \
|
||||
} \
|
||||
\
|
||||
if (_parentManagesVisibilityDepth) { \
|
||||
return [(id <ASManagesChildVisibilityDepth>)self.parentViewController visibilityDepthOfChildViewController:self]; \
|
||||
} \
|
||||
return _visibilityDepth; \
|
||||
}
|
||||
|
||||
#define ASVisibilityViewDidDisappearImplementation \
|
||||
- (void)viewDidDisappear:(BOOL)animated \
|
||||
{ \
|
||||
[super viewDidDisappear:animated]; \
|
||||
\
|
||||
if (_parentManagesVisibilityDepth == NO) { \
|
||||
[self setVisibilityDepth:1]; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ASVisibilityViewWillAppear \
|
||||
- (void)viewWillAppear:(BOOL)animated \
|
||||
{ \
|
||||
[super viewWillAppear:animated]; \
|
||||
\
|
||||
if (_parentManagesVisibilityDepth == NO) { \
|
||||
[self setVisibilityDepth:0]; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ASVisibilityDidMoveToParentViewController \
|
||||
- (void)didMoveToParentViewController:(UIViewController *)parent \
|
||||
{ \
|
||||
[super didMoveToParentViewController:parent]; \
|
||||
[self visibilityDepthDidChange]; \
|
||||
}
|
||||
23
AsyncDisplayKit/ASVisibilityProtocols.m
Normal file
23
AsyncDisplayKit/ASVisibilityProtocols.m
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// ASVisibilityProtocols.m
|
||||
// Pods
|
||||
//
|
||||
// Created by Garrett Moon on 4/28/16.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "ASVisibilityProtocols.h"
|
||||
|
||||
ASLayoutRangeMode ASLayoutRangeModeForVisibilityDepth(NSUInteger visibilityDepth)
|
||||
{
|
||||
if (visibilityDepth == 0) {
|
||||
return ASLayoutRangeModeFull;
|
||||
} else if (visibilityDepth == 1) {
|
||||
return ASLayoutRangeModeMinimum;
|
||||
} else if (visibilityDepth == 2) {
|
||||
return ASLayoutRangeModeVisibleOnly;
|
||||
}
|
||||
return ASLayoutRangeModeLowMemory;
|
||||
}
|
||||
@ -34,6 +34,8 @@
|
||||
#import <AsyncDisplayKit/ASPagerNode.h>
|
||||
|
||||
#import <AsyncDisplayKit/ASViewController.h>
|
||||
#import <AsyncDisplayKit/ASNavigationController.h>
|
||||
#import <AsyncDisplayKit/ASTabBarController.h>
|
||||
#import <AsyncDisplayKit/ASRangeControllerUpdateRangeProtocol+Beta.h>
|
||||
|
||||
#import <AsyncDisplayKit/ASChangeSetDataController.h>
|
||||
@ -77,6 +79,8 @@
|
||||
#import <AsyncDisplayKit/UIView+ASConvenience.h>
|
||||
#import <AsyncDisplayKit/ASRunLoopQueue.h>
|
||||
#import <AsyncDisplayKit/ASTextKitComponents.h>
|
||||
#import <AsyncDisplayKit/ASTraitCollection.h>
|
||||
#import <AsyncDisplayKit/ASVisibilityProtocols.h>
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit+Debug.h>
|
||||
|
||||
|
||||
@ -51,7 +51,9 @@
|
||||
|
||||
- (void)willReloadData
|
||||
{
|
||||
[_pendingContexts enumerateKeysAndObjectsUsingBlock:^(NSString *kind, NSMutableArray<ASIndexedNodeContext *> *contexts, BOOL *stop) {
|
||||
NSArray *keys = _pendingContexts.allKeys;
|
||||
for (NSString *kind in keys) {
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = _pendingContexts[kind];
|
||||
// Remove everything that existed before the reload, now that we're ready to insert replacements
|
||||
NSArray *indexPaths = [self indexPathsForEditingNodesOfKind:kind];
|
||||
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
@ -72,7 +74,7 @@
|
||||
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
}];
|
||||
[_pendingContexts removeObjectForKey:kind];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)prepareForInsertSections:(NSIndexSet *)sections
|
||||
@ -87,7 +89,9 @@
|
||||
|
||||
- (void)willInsertSections:(NSIndexSet *)sections
|
||||
{
|
||||
[_pendingContexts enumerateKeysAndObjectsUsingBlock:^(NSString *kind, NSMutableArray<ASIndexedNodeContext *> *contexts, BOOL *stop) {
|
||||
NSArray *keys = _pendingContexts.allKeys;
|
||||
for (NSString *kind in keys) {
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = _pendingContexts[kind];
|
||||
NSMutableArray *sectionArray = [NSMutableArray arrayWithCapacity:sections.count];
|
||||
for (NSUInteger i = 0; i < sections.count; i++) {
|
||||
[sectionArray addObject:[NSMutableArray array]];
|
||||
@ -98,7 +102,7 @@
|
||||
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
}];
|
||||
[_pendingContexts removeObjectForKey:kind];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)willDeleteSections:(NSIndexSet *)sections
|
||||
@ -122,7 +126,9 @@
|
||||
|
||||
- (void)willReloadSections:(NSIndexSet *)sections
|
||||
{
|
||||
[_pendingContexts enumerateKeysAndObjectsUsingBlock:^(NSString *kind, NSMutableArray<ASIndexedNodeContext *> *contexts, BOOL *stop) {
|
||||
NSArray *keys = _pendingContexts.allKeys;
|
||||
for (NSString *kind in keys) {
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = _pendingContexts[kind];
|
||||
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet([self editingNodesOfKind:kind], sections);
|
||||
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
// reinsert the elements
|
||||
@ -130,7 +136,7 @@
|
||||
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
}];
|
||||
[_pendingContexts removeObjectForKey:kind];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection
|
||||
|
||||
@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class ASCellNode;
|
||||
@class ASDataController;
|
||||
@protocol ASEnvironment;
|
||||
|
||||
typedef NSUInteger ASDataControllerAnimationOptions;
|
||||
|
||||
@ -64,6 +65,11 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind;
|
||||
*/
|
||||
- (void)dataControllerUnlockDataSource;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@protocol ASDataControllerEnvironmentDelegate
|
||||
- (id<ASEnvironment>)dataControllerEnvironment;
|
||||
@end
|
||||
|
||||
/**
|
||||
@ -122,6 +128,11 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind;
|
||||
*/
|
||||
@property (nonatomic, weak) id<ASDataControllerDelegate> delegate;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@property (nonatomic, weak) id<ASDataControllerEnvironmentDelegate> environmentDelegate;
|
||||
|
||||
/**
|
||||
* Designated initializer.
|
||||
*
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#import "ASAssert.h"
|
||||
#import "ASCellNode.h"
|
||||
#import "ASDisplayNode.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASFlowLayoutController.h"
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASLayout.h"
|
||||
@ -190,26 +191,32 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
for (NSUInteger j = 0; j < nodeCount; j += kASDataControllerSizingCountPerProcessor) {
|
||||
NSInteger batchCount = MIN(kASDataControllerSizingCountPerProcessor, nodeCount - j);
|
||||
|
||||
__block NSArray *subarray;
|
||||
// Allocate nodes concurrently.
|
||||
__block NSArray *subarrayOfContexts;
|
||||
__block NSArray *subarrayOfNodes;
|
||||
dispatch_block_t allocationBlock = ^{
|
||||
__strong ASIndexedNodeContext **allocatedContextBuffer = (__strong ASIndexedNodeContext **)calloc(batchCount, sizeof(ASIndexedNodeContext *));
|
||||
__strong ASCellNode **allocatedNodeBuffer = (__strong ASCellNode **)calloc(batchCount, sizeof(ASCellNode *));
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
dispatch_apply(batchCount, queue, ^(size_t i) {
|
||||
unsigned long k = j + i;
|
||||
ASCellNode *node = [contexts[k] allocateNode];
|
||||
ASIndexedNodeContext *context = contexts[k];
|
||||
ASCellNode *node = [context allocateNode];
|
||||
if (node == nil) {
|
||||
ASDisplayNodeAssertNotNil(node, @"Node block created nil node; %@, %@", self, self.dataSource);
|
||||
node = [[ASCellNode alloc] init]; // Fallback to avoid crash for production apps.
|
||||
}
|
||||
allocatedNodeBuffer[i] = node;
|
||||
allocatedContextBuffer[i] = context;
|
||||
});
|
||||
subarray = [[NSArray alloc] initWithObjects:allocatedNodeBuffer count:batchCount];
|
||||
|
||||
subarrayOfNodes = [NSArray arrayWithObjects:allocatedNodeBuffer count:batchCount];
|
||||
subarrayOfContexts = [NSArray arrayWithObjects:allocatedContextBuffer count:batchCount];
|
||||
// Nil out buffer indexes to allow arc to free the stored cells.
|
||||
for (int i = 0; i < batchCount; i++) {
|
||||
allocatedContextBuffer[i] = nil;
|
||||
allocatedNodeBuffer[i] = nil;
|
||||
}
|
||||
free(allocatedContextBuffer);
|
||||
free(allocatedNodeBuffer);
|
||||
};
|
||||
|
||||
@ -224,15 +231,15 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
});
|
||||
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
|
||||
|
||||
[self _layoutNodes:subarray fromContexts:contexts atIndexesOfRange:batchRange ofKind:kind];
|
||||
[self _layoutNodes:subarrayOfNodes fromContexts:subarrayOfContexts atIndexesOfRange:batchRange ofKind:kind];
|
||||
} else {
|
||||
allocationBlock();
|
||||
[_mainSerialQueue performBlockOnMainThread:^{
|
||||
[self _layoutNodes:subarray fromContexts:contexts atIndexesOfRange:batchRange ofKind:kind];
|
||||
[self _layoutNodes:subarrayOfNodes fromContexts:subarrayOfContexts atIndexesOfRange:batchRange ofKind:kind];
|
||||
}];
|
||||
}
|
||||
|
||||
[allocatedNodes addObjectsFromArray:subarray];
|
||||
[allocatedNodes addObjectsFromArray:subarrayOfNodes];
|
||||
|
||||
dispatch_group_async(layoutGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
// We should already have measured loaded nodes before we left the main thread. Layout the remaining ones on a background thread.
|
||||
@ -519,8 +526,17 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
for (NSUInteger i = 0; i < rowNum; i++) {
|
||||
NSIndexPath *indexPath = [sectionIndex indexPathByAddingIndex:i];
|
||||
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath];
|
||||
|
||||
// When creating a node, make sure to pass along the current display traits so it will be laid out properly
|
||||
ASCellNodeBlock nodeBlockPropagatingDisplayTraits = ^{
|
||||
ASCellNode *cellNode = nodeBlock();
|
||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
ASEnvironmentStatePropagateDown(cellNode, [environment environmentTraitCollection]);
|
||||
return cellNode;
|
||||
};
|
||||
|
||||
ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:ASDataControllerRowNodeKind atIndexPath:indexPath];
|
||||
[contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlock
|
||||
[contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlockPropagatingDisplayTraits
|
||||
indexPath:indexPath
|
||||
constrainedSize:constrainedSize]];
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@
|
||||
- (BOOL)interceptsSelector:(SEL)selector
|
||||
{
|
||||
return (
|
||||
// handled by ASPagerNodeDataSource node<->cell machinery
|
||||
// handled by ASPagerDataSource node<->cell machinery
|
||||
selector == @selector(collectionView:nodeForItemAtIndexPath:) ||
|
||||
selector == @selector(collectionView:nodeBlockForItemAtIndexPath:) ||
|
||||
selector == @selector(collectionView:numberOfItemsInSection:) ||
|
||||
@ -125,7 +125,15 @@
|
||||
if (_target) {
|
||||
return [_target respondsToSelector:aSelector] ? _target : nil;
|
||||
} else {
|
||||
[_interceptor proxyTargetHasDeallocated:self];
|
||||
// The _interceptor needs to be nilled out in this scenario. For that a strong reference needs to be created
|
||||
// to be able to nil out the _interceptor but still let it know that the proxy target has deallocated
|
||||
// We have to hold a strong reference to the interceptor as we have to nil it out and call the proxyTargetHasDeallocated
|
||||
// The reason that the interceptor needs to be nilled out is that there maybe a change of a infinite loop, for example
|
||||
// if a method will be called in the proxyTargetHasDeallocated: that again would trigger a whole new forwarding cycle
|
||||
id <ASDelegateProxyInterceptor> interceptor = _interceptor;
|
||||
_interceptor = nil;
|
||||
[interceptor proxyTargetHasDeallocated:self];
|
||||
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
#import "ASStackLayoutDefines.h"
|
||||
#import "ASRelativeSize.h"
|
||||
|
||||
@protocol ASEnvironment;
|
||||
@class UITraitCollection;
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_BEGIN
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@ -59,17 +61,49 @@ typedef struct ASEnvironmentHierarchyState {
|
||||
unsigned layoutPending:1; // = NO
|
||||
} ASEnvironmentHierarchyState;
|
||||
|
||||
#pragma mark - ASEnvironmentDisplayTraits
|
||||
|
||||
typedef struct ASEnvironmentTraitCollection {
|
||||
CGFloat displayScale;
|
||||
UIUserInterfaceSizeClass horizontalSizeClass;
|
||||
UIUserInterfaceIdiom userInterfaceIdiom;
|
||||
UIUserInterfaceSizeClass verticalSizeClass;
|
||||
UIForceTouchCapability forceTouchCapability;
|
||||
|
||||
// WARNING:
|
||||
// This pointer is in a C struct and therefore not managed by ARC. It is
|
||||
// an unsafe unretained pointer, so when you dereference it you better be
|
||||
// sure that it is valid.
|
||||
//
|
||||
// Use displayContext when you wish to pass view context specific data along with the
|
||||
// display traits to subnodes. This should be a piece of data owned by an
|
||||
// ASViewController, which will ensure that the data is still valid when laying out
|
||||
// its subviews. When the VC is dealloc'ed, the displayContext it created will also
|
||||
// be dealloced but any subnodes that are hanging around (why would they be?) will now
|
||||
// have a displayContext that points to a bad pointer.
|
||||
//
|
||||
// As an added precaution ASDisplayTraitsClearDisplayContext is called from ASVC's desctructor
|
||||
// which will propagate a nil displayContext to its subnodes.
|
||||
id __unsafe_unretained displayContext;
|
||||
} ASEnvironmentTraitCollection;
|
||||
|
||||
extern void ASEnvironmentTraitCollectionUpdateDisplayContext(id<ASEnvironment> rootEnvironment, id _Nullable context);
|
||||
|
||||
extern ASEnvironmentTraitCollection ASEnvironmentTraitCollectionFromUITraitCollection(UITraitCollection *traitCollection);
|
||||
extern BOOL ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(ASEnvironmentTraitCollection lhs, ASEnvironmentTraitCollection rhs);
|
||||
|
||||
#pragma mark - ASEnvironmentState
|
||||
|
||||
typedef struct ASEnvironmentState {
|
||||
struct ASEnvironmentHierarchyState hierarchyState;
|
||||
struct ASEnvironmentLayoutOptionsState layoutOptionsState;
|
||||
struct ASEnvironmentTraitCollection traitCollection;
|
||||
} ASEnvironmentState;
|
||||
extern ASEnvironmentState ASEnvironmentStateMakeDefault();
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_END
|
||||
|
||||
@class ASTraitCollection;
|
||||
|
||||
#pragma mark - ASEnvironment
|
||||
|
||||
@ -93,6 +127,41 @@ ASDISPLAYNODE_EXTERN_C_END
|
||||
/// Classes should implement this method and return YES / NO dependent if upward propagation is enabled or not
|
||||
- (BOOL)supportsUpwardPropagation;
|
||||
|
||||
/// Classes should implement this method and return YES / NO dependent if downware propagation is enabled or not
|
||||
- (BOOL)supportsTraitsCollectionPropagation;
|
||||
|
||||
/// Returns an NSObject-representation of the environment's ASEnvironmentDisplayTraits
|
||||
- (ASTraitCollection *)asyncTraitCollection;
|
||||
|
||||
/// Returns a struct-representation of the environment's ASEnvironmentDisplayTraits. This only exists as a internal
|
||||
/// convenience method. Users should access the trait collections through the NSObject based asyncTraitCollection API
|
||||
- (ASEnvironmentTraitCollection)environmentTraitCollection;
|
||||
|
||||
@end
|
||||
|
||||
// ASCollection/TableNodes don't actually have ASCellNodes as subnodes. Because of this we can't rely on display trait
|
||||
// downward propagation via ASEnvironment. Instead if the new environmentState has displayTraits that are different from
|
||||
// the cells', then we propagate downward explicitly and request a relayout.
|
||||
//
|
||||
// If there is any new downward propagating state, it should be added to this define.
|
||||
//
|
||||
// This logic is used in both ASCollectionNode and ASTableNode
|
||||
#define ASEnvironmentCollectionTableSetEnvironmentState(lock) \
|
||||
- (void)setEnvironmentState:(ASEnvironmentState)environmentState\
|
||||
{\
|
||||
ASDN::MutexLocker l(lock);\
|
||||
ASEnvironmentTraitCollection oldTraits = self.environmentState.traitCollection;\
|
||||
[super setEnvironmentState:environmentState];\
|
||||
ASEnvironmentTraitCollection currentTraits = environmentState.traitCollection;\
|
||||
if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(currentTraits, oldTraits) == NO) {\
|
||||
NSArray<NSArray <ASCellNode *> *> *completedNodes = [self.view.dataController completedNodes];\
|
||||
for (NSArray *sectionArray in completedNodes) {\
|
||||
for (ASCellNode *cellNode in sectionArray) {\
|
||||
ASEnvironmentStatePropagateDown(cellNode, currentTraits);\
|
||||
[cellNode setNeedsLayout];\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -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 "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()
|
||||
};
|
||||
}
|
||||
83
AsyncDisplayKit/Details/ASEnvironment.mm
Normal file
83
AsyncDisplayKit/Details/ASEnvironment.mm
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import <AsyncDisplayKit/ASAvailability.h>
|
||||
|
||||
ASEnvironmentLayoutOptionsState _ASEnvironmentLayoutOptionsStateMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentLayoutOptionsState) {
|
||||
// Default values can be defined in here
|
||||
};
|
||||
}
|
||||
|
||||
ASEnvironmentHierarchyState _ASEnvironmentHierarchyStateMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentHierarchyState) {
|
||||
// Default values can be defined in here
|
||||
};
|
||||
}
|
||||
|
||||
extern void ASEnvironmentTraitCollectionUpdateDisplayContext(id<ASEnvironment> rootEnvironment, id context)
|
||||
{
|
||||
ASEnvironmentState envState = [rootEnvironment environmentState];
|
||||
ASEnvironmentTraitCollection displayTraits = envState.traitCollection;
|
||||
displayTraits.displayContext = context;
|
||||
envState.traitCollection = displayTraits;
|
||||
[rootEnvironment setEnvironmentState:envState];
|
||||
|
||||
for (id<ASEnvironment> child in [rootEnvironment children]) {
|
||||
ASEnvironmentStatePropagateDown(child, displayTraits);
|
||||
}
|
||||
}
|
||||
|
||||
ASEnvironmentTraitCollection _ASEnvironmentTraitCollectionMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentTraitCollection) {
|
||||
// Default values can be defined in here
|
||||
};
|
||||
}
|
||||
|
||||
ASEnvironmentTraitCollection ASEnvironmentTraitCollectionFromUITraitCollection(UITraitCollection *traitCollection)
|
||||
{
|
||||
ASEnvironmentTraitCollection asyncTraitCollection;
|
||||
if (AS_AT_LEAST_IOS8) {
|
||||
asyncTraitCollection.displayScale = traitCollection.displayScale;
|
||||
asyncTraitCollection.horizontalSizeClass = traitCollection.horizontalSizeClass;
|
||||
asyncTraitCollection.verticalSizeClass = traitCollection.verticalSizeClass;
|
||||
asyncTraitCollection.userInterfaceIdiom = traitCollection.userInterfaceIdiom;
|
||||
if (AS_AT_LEAST_IOS9) {
|
||||
asyncTraitCollection.forceTouchCapability = traitCollection.forceTouchCapability;
|
||||
}
|
||||
}
|
||||
return asyncTraitCollection;
|
||||
}
|
||||
|
||||
BOOL ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(ASEnvironmentTraitCollection lhs, ASEnvironmentTraitCollection rhs)
|
||||
{
|
||||
return
|
||||
lhs.verticalSizeClass == rhs.verticalSizeClass &&
|
||||
lhs.horizontalSizeClass == rhs.horizontalSizeClass &&
|
||||
lhs.displayScale == rhs.displayScale &&
|
||||
lhs.userInterfaceIdiom == rhs.userInterfaceIdiom &&
|
||||
lhs.forceTouchCapability == rhs.forceTouchCapability &&
|
||||
lhs.displayContext == rhs.displayContext;
|
||||
}
|
||||
|
||||
ASEnvironmentState ASEnvironmentStateMakeDefault()
|
||||
{
|
||||
return (ASEnvironmentState) {
|
||||
.layoutOptionsState = _ASEnvironmentLayoutOptionsStateMakeDefault(),
|
||||
.hierarchyState = _ASEnvironmentHierarchyStateMakeDefault(),
|
||||
.traitCollection = _ASEnvironmentTraitCollectionMakeDefault()
|
||||
};
|
||||
}
|
||||
|
||||
@ -61,7 +61,16 @@ typedef void(^ASImageCacherCompletion)(id <ASImageContainerProtocol> _Nullable i
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
@param image The image that was downloaded, if the image could be successfully downloaded; nil otherwise.
|
||||
@param error An error describing why the download of `URL` failed, if the download failed; nil otherwise.
|
||||
@param downloadIdentifier The identifier for the download task that completed.
|
||||
*/
|
||||
typedef void(^ASImageDownloaderCompletion)(id <ASImageContainerProtocol> _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier);
|
||||
|
||||
/**
|
||||
@param progress The progress of the download, in the range of (0.0, 1.0), inclusive.
|
||||
*/
|
||||
typedef void(^ASImageDownloaderProgress)(CGFloat progress);
|
||||
typedef void(^ASImageDownloaderProgressImage)(UIImage *progressImage, CGFloat progress, id _Nullable downloadIdentifier);
|
||||
|
||||
@ -98,10 +107,7 @@ typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) {
|
||||
@param URL The URL of the image to download.
|
||||
@param callbackQueue The queue to call `downloadProgressBlock` and `completion` on.
|
||||
@param downloadProgress The block to be invoked when the download of `URL` progresses.
|
||||
@param progress The progress of the download, in the range of (0.0, 1.0), inclusive.
|
||||
@param completion The block to be invoked when the download has completed, or has failed.
|
||||
@param image The image that was downloaded, if the image could be successfully downloaded; nil otherwise.
|
||||
@param error An error describing why the download of `URL` failed, if the download failed; nil otherwise.
|
||||
@discussion This method is likely to be called on the main thread, so any custom implementations should make sure to background any expensive download operations.
|
||||
@result An opaque identifier to be used in canceling the download, via `cancelImageDownloadForIdentifier:`. You must
|
||||
retain the identifier if you wish to use it later.
|
||||
@ -109,7 +115,7 @@ typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) {
|
||||
- (nullable id)downloadImageWithURL:(NSURL *)URL
|
||||
callbackQueue:(dispatch_queue_t)callbackQueue
|
||||
downloadProgress:(nullable ASImageDownloaderProgress)downloadProgress
|
||||
completion:(nullable ASImageDownloaderCompletion)completion;
|
||||
completion:(ASImageDownloaderCompletion)completion;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -9,8 +9,12 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ASImageProtocols.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface ASPINRemoteImageDownloader : NSObject <ASImageCacheProtocol, ASImageDownloaderProtocol>
|
||||
|
||||
+ (instancetype)sharedDownloader;
|
||||
+ (ASPINRemoteImageDownloader *)sharedDownloader;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -96,8 +96,9 @@
|
||||
|
||||
- (id <ASImageContainerProtocol>)synchronouslyFetchedCachedImageWithURL:(NSURL *)URL;
|
||||
{
|
||||
NSString *key = [[self sharedPINRemoteImageManager] cacheKeyForURL:URL processorKey:nil];
|
||||
PINRemoteImageManagerResult *result = [[self sharedPINRemoteImageManager] synchronousImageFromCacheWithCacheKey:key options:PINRemoteImageManagerDownloadOptionsSkipDecode];
|
||||
PINRemoteImageManager *manager = [self sharedPINRemoteImageManager];
|
||||
NSString *key = [manager cacheKeyForURL:URL processorKey:nil];
|
||||
PINRemoteImageManagerResult *result = [manager synchronousImageFromCacheWithCacheKey:key options:PINRemoteImageManagerDownloadOptionsSkipDecode];
|
||||
#if PIN_ANIMATED_AVAILABLE
|
||||
if (result.alternativeRepresentation) {
|
||||
return result.alternativeRepresentation;
|
||||
@ -133,7 +134,18 @@
|
||||
downloadProgress:(ASImageDownloaderProgress)downloadProgress
|
||||
completion:(ASImageDownloaderCompletion)completion;
|
||||
{
|
||||
return [[self sharedPINRemoteImageManager] downloadImageWithURL:URL options:PINRemoteImageManagerDownloadOptionsSkipDecode completion:^(PINRemoteImageManagerResult *result) {
|
||||
return [[self sharedPINRemoteImageManager] downloadImageWithURL:URL options:PINRemoteImageManagerDownloadOptionsSkipDecode progressDownload:^(int64_t completedBytes, int64_t totalBytes) {
|
||||
if (downloadProgress == nil) { return; }
|
||||
|
||||
/// If we're targeting the main queue and we're on the main thread, call immediately.
|
||||
if (ASDisplayNodeThreadIsMain() && callbackQueue == dispatch_get_main_queue()) {
|
||||
downloadProgress(totalBytes / (CGFloat)completedBytes);
|
||||
} else {
|
||||
dispatch_async(callbackQueue, ^{
|
||||
downloadProgress(totalBytes / (CGFloat)completedBytes);
|
||||
});
|
||||
}
|
||||
} completion:^(PINRemoteImageManagerResult * _Nonnull result) {
|
||||
/// If we're targeting the main queue and we're on the main thread, complete immediately.
|
||||
if (ASDisplayNodeThreadIsMain() && callbackQueue == dispatch_get_main_queue()) {
|
||||
#if PIN_ANIMATED_AVAILABLE
|
||||
|
||||
54
AsyncDisplayKit/Details/ASTraitCollection.h
Normal file
54
AsyncDisplayKit/Details/ASTraitCollection.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 <UIKit/UIKit.h>
|
||||
#import <AsyncDisplayKit/ASEnvironment.h>
|
||||
|
||||
@interface ASTraitCollection : NSObject
|
||||
|
||||
@property (nonatomic, assign, readonly) CGFloat displayScale;
|
||||
@property (nonatomic, assign, readonly) UIUserInterfaceSizeClass horizontalSizeClass;
|
||||
@property (nonatomic, assign, readonly) UIUserInterfaceIdiom userInterfaceIdiom;
|
||||
@property (nonatomic, assign, readonly) UIUserInterfaceSizeClass verticalSizeClass;
|
||||
@property (nonatomic, assign, readonly) UIForceTouchCapability forceTouchCapability;
|
||||
|
||||
/**
|
||||
* An optional context to pass along with an ASTraitCollection.
|
||||
* This can be used to pass any internal state to all subnodes via the ASTraitCollection that is not
|
||||
* included in UITraitCollection. This could range from more fine-tuned size classes to a class of
|
||||
* constants that is based upon the new trait collection.
|
||||
*
|
||||
* Be aware that internally this context is held by a C struct which cannot retain the pointer.
|
||||
* ASTraitCollection is generally a very short-lived class, existing only to provide a non-struct API
|
||||
* to trait collections. When an ASTraitCollection is returned via one of ASViewController's 2
|
||||
* custom trait collection creation blocks, traitColectionContext is assigned to the VC's traitColectionContext.
|
||||
* This makes sure that the VC is the owner of the context and ASEnvironmentTraitCollections will not
|
||||
* have a reference to a dangling pointer.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) id traitCollectionContext;
|
||||
|
||||
|
||||
+ (ASTraitCollection *)traitCollectionWithASEnvironmentTraitCollection:(ASEnvironmentTraitCollection)traits;
|
||||
|
||||
+ (ASTraitCollection *)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection
|
||||
traitCollectionContext:(id)traitCollectionContext;
|
||||
|
||||
|
||||
+ (ASTraitCollection *)traitCollectionWithDisplayScale:(CGFloat)displayScale
|
||||
userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
|
||||
horizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass
|
||||
verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass
|
||||
forceTouchCapability:(UIForceTouchCapability)forceTouchCapability
|
||||
traitCollectionContext:(id)traitCollectionContext;
|
||||
|
||||
|
||||
- (ASEnvironmentTraitCollection)environmentTraitCollection;
|
||||
|
||||
@end
|
||||
98
AsyncDisplayKit/Details/ASTraitCollection.m
Normal file
98
AsyncDisplayKit/Details/ASTraitCollection.m
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// ASDisplayTraits.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Ricky Cancro on 5/4/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASTraitCollection.h"
|
||||
#import <AsyncDisplayKit/ASAssert.h>
|
||||
#import <AsyncDisplayKit/ASAvailability.h>
|
||||
|
||||
@implementation ASTraitCollection
|
||||
|
||||
- (instancetype)initWithDisplayScale:(CGFloat)displayScale
|
||||
userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
|
||||
horizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass
|
||||
verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass
|
||||
forceTouchCapability:(UIForceTouchCapability)forceTouchCapability
|
||||
traitCollectionContext:(id)traitCollectionContext
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_displayScale = displayScale;
|
||||
_userInterfaceIdiom = userInterfaceIdiom;
|
||||
_horizontalSizeClass = horizontalSizeClass;
|
||||
_verticalSizeClass = verticalSizeClass;
|
||||
_forceTouchCapability = forceTouchCapability;
|
||||
_traitCollectionContext = traitCollectionContext;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (ASTraitCollection *)traitCollectionWithDisplayScale:(CGFloat)displayScale
|
||||
userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
|
||||
horizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass
|
||||
verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass
|
||||
forceTouchCapability:(UIForceTouchCapability)forceTouchCapability
|
||||
traitCollectionContext:(id)traitCollectionContext
|
||||
{
|
||||
return [[[self class] alloc] initWithDisplayScale:displayScale
|
||||
userInterfaceIdiom:userInterfaceIdiom
|
||||
horizontalSizeClass:horizontalSizeClass
|
||||
verticalSizeClass:verticalSizeClass
|
||||
forceTouchCapability:forceTouchCapability
|
||||
traitCollectionContext:traitCollectionContext];
|
||||
}
|
||||
|
||||
+ (ASTraitCollection *)traitCollectionWithASEnvironmentTraitCollection:(ASEnvironmentTraitCollection)traits
|
||||
{
|
||||
return [[[self class] alloc] initWithDisplayScale:traits.displayScale
|
||||
userInterfaceIdiom:traits.userInterfaceIdiom
|
||||
horizontalSizeClass:traits.horizontalSizeClass
|
||||
verticalSizeClass:traits.verticalSizeClass
|
||||
forceTouchCapability:traits.forceTouchCapability
|
||||
traitCollectionContext:traits.displayContext];
|
||||
|
||||
}
|
||||
|
||||
+ (ASTraitCollection *)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection
|
||||
traitCollectionContext:(id)traitCollectionContext
|
||||
{
|
||||
ASTraitCollection *asyncTraitCollection = nil;
|
||||
if (AS_AT_LEAST_IOS9) {
|
||||
asyncTraitCollection = [[[self class] alloc] initWithDisplayScale:traitCollection.displayScale
|
||||
userInterfaceIdiom:traitCollection.userInterfaceIdiom
|
||||
horizontalSizeClass:traitCollection.horizontalSizeClass
|
||||
verticalSizeClass:traitCollection.verticalSizeClass
|
||||
forceTouchCapability:traitCollection.forceTouchCapability
|
||||
traitCollectionContext:traitCollectionContext];
|
||||
}
|
||||
else if (AS_AT_LEAST_IOS8) {
|
||||
asyncTraitCollection = [[[self class] alloc] initWithDisplayScale:traitCollection.displayScale
|
||||
userInterfaceIdiom:traitCollection.userInterfaceIdiom
|
||||
horizontalSizeClass:traitCollection.horizontalSizeClass
|
||||
verticalSizeClass:traitCollection.verticalSizeClass
|
||||
forceTouchCapability:0
|
||||
traitCollectionContext:traitCollectionContext];
|
||||
} else {
|
||||
asyncTraitCollection = [[[self class] alloc] init];
|
||||
}
|
||||
|
||||
return asyncTraitCollection;
|
||||
}
|
||||
|
||||
- (ASEnvironmentTraitCollection)environmentTraitCollection
|
||||
{
|
||||
return (ASEnvironmentTraitCollection) {
|
||||
.displayScale = self.displayScale,
|
||||
.horizontalSizeClass = self.horizontalSizeClass,
|
||||
.userInterfaceIdiom = self.userInterfaceIdiom,
|
||||
.verticalSizeClass = self.verticalSizeClass,
|
||||
.forceTouchCapability = self.forceTouchCapability,
|
||||
.displayContext = self.traitCollectionContext,
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@ -82,8 +82,8 @@ static void _transactionGroupRunLoopObserverCallback(CFRunLoopObserverRef observ
|
||||
ASDisplayNodeAssertMainThread();
|
||||
|
||||
if ([_containerLayers count]) {
|
||||
NSHashTable *containerLayersToCommit = [_containerLayers copy];
|
||||
[_containerLayers removeAllObjects];
|
||||
NSHashTable *containerLayersToCommit = _containerLayers;
|
||||
_containerLayers = [NSHashTable hashTableWithOptions:NSPointerFunctionsObjectPointerPersonality];
|
||||
|
||||
for (CALayer *containerLayer in containerLayersToCommit) {
|
||||
// Note that the act of committing a transaction may open a new transaction,
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASLayout.h"
|
||||
#import "ASThread.h"
|
||||
#import "ASTraitCollection.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import <vector>
|
||||
@ -184,6 +185,11 @@
|
||||
return ASEnvironmentStatePropagationEnabled();
|
||||
}
|
||||
|
||||
- (BOOL)supportsTraitsCollectionPropagation
|
||||
{
|
||||
return ASEnvironmentStateTraitCollectionPropagationEnabled();
|
||||
}
|
||||
|
||||
- (void)propagateUpLayoutable:(id<ASLayoutable>)layoutable
|
||||
{
|
||||
if ([layoutable isKindOfClass:[ASLayoutSpec class]]) {
|
||||
@ -193,9 +199,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (ASEnvironmentTraitCollection)environmentTraitCollection
|
||||
{
|
||||
return _environmentState.traitCollection;
|
||||
}
|
||||
|
||||
ASEnvironmentLayoutOptionsForwarding
|
||||
ASEnvironmentLayoutExtensibilityForwarding
|
||||
|
||||
- (ASTraitCollection *)asyncTraitCollection
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return [ASTraitCollection traitCollectionWithASEnvironmentTraitCollection:_environmentState.traitCollection];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASLayoutSpec (Debugging)
|
||||
|
||||
@ -228,4 +228,10 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
|
||||
*/
|
||||
- (ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass checkViewHierarchy:(BOOL)checkViewHierarchy;
|
||||
|
||||
/**
|
||||
* Convenience method to access this node's trait collection struct. Externally, users should interact
|
||||
* with the trait collection via ASTraitCollection
|
||||
*/
|
||||
- (ASEnvironmentTraitCollection)environmentTraitCollection;
|
||||
|
||||
@end
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
BOOL ASEnvironmentStatePropagationEnabled();
|
||||
BOOL ASEnvironmentStateTraitCollectionPropagationEnabled();
|
||||
|
||||
|
||||
#pragma mark - Set and get extensible values for layout options
|
||||
@ -45,10 +46,12 @@ static const struct ASEnvironmentStateExtensions ASEnvironmentDefaultStateExtens
|
||||
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);
|
||||
|
||||
static const struct ASEnvironmentTraitCollection ASEnvironmentDefaultTraitCollection = {};
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentTraitCollection state, ASEnvironmentStatePropagation propagation);
|
||||
|
||||
|
||||
#pragma mark - Propagation
|
||||
|
||||
|
||||
@ -15,13 +15,18 @@
|
||||
//#define LOG(...) NSLog(__VA_ARGS__)
|
||||
#define LOG(...)
|
||||
|
||||
#define AS_SUPPORT_PROPAGATION NO
|
||||
#define AS_SUPPORT_PROPAGATION YES
|
||||
#define AS_DOES_NOT_SUPPORT_PROPAGATION NO
|
||||
|
||||
BOOL ASEnvironmentStatePropagationEnabled()
|
||||
{
|
||||
return AS_SUPPORT_PROPAGATION;
|
||||
return AS_DOES_NOT_SUPPORT_PROPAGATION;
|
||||
}
|
||||
|
||||
BOOL ASEnvironmentStateTraitCollectionPropagationEnabled()
|
||||
{
|
||||
return AS_SUPPORT_PROPAGATION;
|
||||
}
|
||||
|
||||
#pragma mark - Traversing an ASEnvironment Tree
|
||||
|
||||
@ -106,15 +111,15 @@ UIEdgeInsets _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(id<ASEnvir
|
||||
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState hierarchyState, ASEnvironmentStatePropagation propagation) {
|
||||
// Merge object and hierarchy state
|
||||
LOG(@"Merge object and state: %@ - ASEnvironmentHierarchyState", object);
|
||||
LOG(@"Merge object and state: %@ - ASEnvironmentHierarchyState", hierarchyState);
|
||||
return environmentState;
|
||||
}
|
||||
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState layoutOptionsState, ASEnvironmentStatePropagation propagation) {
|
||||
// Merge object and layout options state
|
||||
LOG(@"Merge object and state: %@ - ASEnvironmentLayoutOptionsState", object);
|
||||
LOG(@"Merge object and state: %@ - ASEnvironmentLayoutOptionsState", layoutOptionsState);
|
||||
|
||||
if (!ASEnvironmentStatePropagationEnabled()) {
|
||||
if (!ASEnvironmentStatePropagationEnabled() && propagation == ASEnvironmentStatePropagation::UP) {
|
||||
return environmentState;
|
||||
}
|
||||
|
||||
@ -188,3 +193,23 @@ ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environme
|
||||
|
||||
return environmentState;
|
||||
}
|
||||
|
||||
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState childEnvironmentState, ASEnvironmentTraitCollection parentTraitCollection, ASEnvironmentStatePropagation propagation) {
|
||||
if (propagation == ASEnvironmentStatePropagation::DOWN && !ASEnvironmentStateTraitCollectionPropagationEnabled()) {
|
||||
return childEnvironmentState;
|
||||
}
|
||||
|
||||
// Support propagate down
|
||||
if (propagation == ASEnvironmentStatePropagation::DOWN) {
|
||||
ASEnvironmentTraitCollection childTraitCollection = childEnvironmentState.traitCollection;
|
||||
childTraitCollection.horizontalSizeClass = parentTraitCollection.horizontalSizeClass;
|
||||
childTraitCollection.verticalSizeClass = parentTraitCollection.verticalSizeClass;
|
||||
childTraitCollection.userInterfaceIdiom = parentTraitCollection.userInterfaceIdiom;
|
||||
childTraitCollection.forceTouchCapability = parentTraitCollection.forceTouchCapability;
|
||||
childTraitCollection.displayScale = parentTraitCollection.displayScale;
|
||||
childTraitCollection.displayContext = parentTraitCollection.displayContext;
|
||||
childEnvironmentState.traitCollection = childTraitCollection;
|
||||
|
||||
}
|
||||
return childEnvironmentState;
|
||||
}
|
||||
|
||||
@ -137,25 +137,30 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
|
||||
|
||||
- (void)_calculateSize
|
||||
{
|
||||
[self truncater];
|
||||
// if we have no scale factors or an unconstrained width, there is no reason to try to adjust the font size
|
||||
if (isinf(_constrainedSize.width) == NO && [_attributes.pointSizeScaleFactors count] > 0) {
|
||||
_currentScaleFactor = [[self fontSizeAdjuster] scaleFactor];
|
||||
}
|
||||
|
||||
// Force glyph generation and layout, which may not have happened yet (and isn't triggered by
|
||||
// -usedRectForTextContainer:).
|
||||
__block NSTextStorage *scaledTextStorage = nil;
|
||||
BOOL isScaled = [self isScaled];
|
||||
[[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||
if (isScaled) {
|
||||
if (isScaled) {
|
||||
// apply the string scale before truncating or else we may truncate the string after we've done the work to shrink it.
|
||||
[[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||
NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage];
|
||||
[ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:_currentScaleFactor];
|
||||
scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString];
|
||||
|
||||
[textStorage removeLayoutManager:layoutManager];
|
||||
[scaledTextStorage addLayoutManager:layoutManager];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
[[self truncater] truncate];
|
||||
|
||||
// Force glyph generation and layout, which may not have happened yet (and isn't triggered by
|
||||
// -usedRectForTextContainer:).
|
||||
[[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||
[layoutManager ensureLayoutForTextContainer:textContainer];
|
||||
}];
|
||||
|
||||
@ -251,7 +256,9 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
|
||||
|
||||
- (std::vector<NSRange>)visibleRanges
|
||||
{
|
||||
return [self truncater].visibleRanges;
|
||||
ASTextKitTailTruncater *truncater = [self truncater];
|
||||
[truncater truncate];
|
||||
return truncater.visibleRanges;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -30,8 +30,6 @@
|
||||
_context = context;
|
||||
_truncationAttributedString = truncationAttributedString;
|
||||
_avoidTailTruncationSet = avoidTailTruncationSet;
|
||||
|
||||
[self _truncate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -153,7 +151,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_truncate
|
||||
- (void)truncate
|
||||
{
|
||||
[_context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||
NSUInteger originalStringLength = textStorage.length;
|
||||
|
||||
@ -33,4 +33,9 @@
|
||||
truncationAttributedString:(NSAttributedString *)truncationAttributedString
|
||||
avoidTailTruncationSet:(NSCharacterSet *)avoidTailTruncationSet;
|
||||
|
||||
/**
|
||||
* Actually do the truncation.
|
||||
*/
|
||||
- (void)truncate;
|
||||
|
||||
@end
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
|
||||
truncationAttributedString:nil
|
||||
avoidTailTruncationSet:nil];
|
||||
[tailTruncater truncate];
|
||||
XCTAssert(NSEqualRanges(textKitVisibleRange, tailTruncater.visibleRanges[0]));
|
||||
}
|
||||
|
||||
@ -71,6 +72,7 @@
|
||||
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
|
||||
truncationAttributedString:[self _simpleTruncationAttributedString]
|
||||
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@""]];
|
||||
[tailTruncater truncate];
|
||||
__block NSString *drawnString;
|
||||
[context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||
drawnString = textStorage.string;
|
||||
@ -95,7 +97,7 @@
|
||||
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
|
||||
truncationAttributedString:[self _simpleTruncationAttributedString]
|
||||
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]];
|
||||
(void)tailTruncater;
|
||||
[tailTruncater truncate];
|
||||
__block NSString *drawnString;
|
||||
[context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||
drawnString = textStorage.string;
|
||||
@ -120,8 +122,7 @@
|
||||
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
|
||||
truncationAttributedString:[self _simpleTruncationAttributedString]
|
||||
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]];
|
||||
// So Xcode doesn't yell at me for an unused var...
|
||||
(void)tailTruncater;
|
||||
[tailTruncater truncate];
|
||||
__block NSString *drawnString;
|
||||
[context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||
drawnString = textStorage.string;
|
||||
@ -144,9 +145,9 @@
|
||||
layoutManagerDelegate:nil
|
||||
textStorageCreationBlock:nil];
|
||||
|
||||
XCTAssertNoThrow([[ASTextKitTailTruncater alloc] initWithContext:context
|
||||
XCTAssertNoThrow([[[ASTextKitTailTruncater alloc] initWithContext:context
|
||||
truncationAttributedString:[self _simpleTruncationAttributedString]
|
||||
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]]);
|
||||
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]] truncate]);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -44,7 +44,7 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
|
||||
@interface ASTextNodeTests : XCTestCase
|
||||
|
||||
@property (nonatomic, readwrite, strong) ASTextNode *textNode;
|
||||
@property (nonatomic, readwrite, copy) NSAttributedString *attributedString;
|
||||
@property (nonatomic, readwrite, copy) NSAttributedString *attributedText;
|
||||
|
||||
@end
|
||||
|
||||
@ -80,8 +80,8 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
|
||||
[mas addAttribute:NSParagraphStyleAttributeName value:lastLinePara
|
||||
range:NSMakeRange(mas.length - 1, 1)];
|
||||
|
||||
_attributedString = mas;
|
||||
_textNode.attributedString = _attributedString;
|
||||
_attributedText = mas;
|
||||
_textNode.attributedText = _attributedText;
|
||||
}
|
||||
|
||||
#pragma mark - ASTextNode
|
||||
@ -97,8 +97,8 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
|
||||
- (void)testSettingTruncationMessage
|
||||
{
|
||||
NSAttributedString *truncation = [[NSAttributedString alloc] initWithString:@"..." attributes:nil];
|
||||
_textNode.truncationAttributedString = truncation;
|
||||
XCTAssertTrue([_textNode.truncationAttributedString isEqualToAttributedString:truncation], @"Failed to set truncation message");
|
||||
_textNode.truncationAttributedText = truncation;
|
||||
XCTAssertTrue([_textNode.truncationAttributedText isEqualToAttributedString:truncation], @"Failed to set truncation message");
|
||||
}
|
||||
|
||||
- (void)testSettingAdditionalTruncationMessage
|
||||
@ -142,11 +142,11 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
|
||||
|
||||
- (void)testAccessibility
|
||||
{
|
||||
_textNode.attributedString = _attributedString;
|
||||
_textNode.attributedText = _attributedText;
|
||||
XCTAssertTrue(_textNode.isAccessibilityElement, @"Should be an accessibility element");
|
||||
XCTAssertTrue(_textNode.accessibilityTraits == UIAccessibilityTraitStaticText, @"Should have static text accessibility trait, instead has %llu", _textNode.accessibilityTraits);
|
||||
|
||||
XCTAssertTrue([_textNode.accessibilityLabel isEqualToString:_attributedString.string], @"Accessibility label is incorrectly set to \n%@\n when it should be \n%@\n", _textNode.accessibilityLabel, _attributedString.string);
|
||||
XCTAssertTrue([_textNode.accessibilityLabel isEqualToString:_attributedText.string], @"Accessibility label is incorrectly set to \n%@\n when it should be \n%@\n", _textNode.accessibilityLabel, _attributedText.string);
|
||||
}
|
||||
|
||||
- (void)testLinkAttribute
|
||||
@ -156,7 +156,7 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
|
||||
NSString *linkString = @"Link";
|
||||
NSRange linkRange = NSMakeRange(0, linkString.length);
|
||||
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:linkString attributes:@{ linkAttributeName : linkAttributeValue}];
|
||||
_textNode.attributedString = attributedString;
|
||||
_textNode.attributedText = attributedString;
|
||||
_textNode.linkAttributeNames = @[linkAttributeName];
|
||||
|
||||
ASTextNodeTestDelegate *delegate = [ASTextNodeTestDelegate new];
|
||||
@ -178,7 +178,7 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
|
||||
NSString *linkString = @"Link notalink";
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:linkString];
|
||||
[attributedString addAttribute:linkAttributeName value:linkAttributeValue range:NSMakeRange(0, 4)];
|
||||
_textNode.attributedString = attributedString;
|
||||
_textNode.attributedText = attributedString;
|
||||
_textNode.linkAttributeNames = @[linkAttributeName];
|
||||
|
||||
ASTextNodeTestDelegate *delegate = [ASTextNodeTestDelegate new];
|
||||
|
||||
@ -23,6 +23,10 @@
|
||||
#define kCFCoreFoundationVersionNumber_iOS_8_0 1140.1
|
||||
#endif
|
||||
|
||||
#ifndef kCFCoreFoundationVersionNumber_iOS_8_4
|
||||
#define kCFCoreFoundationVersionNumber_iOS_8_4 1145.15
|
||||
#endif
|
||||
|
||||
#ifndef __IPHONE_7_0
|
||||
#define __IPHONE_7_0 70000
|
||||
#endif
|
||||
@ -31,6 +35,10 @@
|
||||
#define __IPHONE_8_0 80000
|
||||
#endif
|
||||
|
||||
#ifndef __IPHONE_9_0
|
||||
#define __IPHONE_9_0 90000
|
||||
#endif
|
||||
|
||||
#ifndef AS_IOS8_SDK_OR_LATER
|
||||
#define AS_IOS8_SDK_OR_LATER __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
|
||||
#endif
|
||||
@ -38,3 +46,4 @@
|
||||
#define AS_AT_LEAST_IOS7 (kCFCoreFoundationVersionNumber > kCFCoreFoundationVersionNumber_iOS_6_1)
|
||||
#define AS_AT_LEAST_IOS7_1 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_1)
|
||||
#define AS_AT_LEAST_IOS8 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0)
|
||||
#define AS_AT_LEAST_IOS9 (kCFCoreFoundationVersionNumber > kCFCoreFoundationVersionNumber_iOS_8_4)
|
||||
|
||||
@ -25,6 +25,9 @@ Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
|
||||
disclosure of security bugs. In those cases, please go through the process
|
||||
outlined on that page and do not file a public issue.
|
||||
|
||||
## Getting Help
|
||||
We use Slack for real-time debugging, community updates, and general talk about ASDK. Signup at http://asdk-slack-auto-invite.herokuapp.com or email AsyncDisplayKit(at)gmail.com to get an invite.
|
||||
|
||||
## Coding Style
|
||||
* 2 spaces for indentation rather than tabs
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
[](http://cocoapods.org/pods/AsyncDisplayKit)
|
||||
[](http://cocoapods.org/pods/AsyncDisplayKit)
|
||||
[](http://asdk-slack-auto-invite.herokuapp.com)
|
||||
|
||||
[](http://AsyncDisplayKit.org)
|
||||
[](http://AsyncDisplayKit.org)
|
||||
@ -98,13 +97,17 @@ You can also easily [create your own
|
||||
nodes](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/ASDisplayNode%2BSubclasses.h)
|
||||
to implement node hierarchies or custom drawing.
|
||||
|
||||
### Learn more
|
||||
## Learn more
|
||||
|
||||
* Read the [Getting Started guide](http://asyncdisplaykit.org/docs/getting-started.html)
|
||||
* Get the [sample projects](https://github.com/facebook/AsyncDisplayKit/tree/master/examples)
|
||||
* Browse the [API reference](http://asyncdisplaykit.org/appledocs.html)
|
||||
* Watch the [NSLondon talk](http://vimeo.com/103589245) or the [NSSpain talk](https://www.youtube.com/watch?v=RY_X7l1g79Q)
|
||||
|
||||
## Getting Help
|
||||
|
||||
We use Slack for real-time debugging, community updates, and general talk about ASDK. Signup at http://asdk-slack-auto-invite.herokuapp.com or email AsyncDisplayKit(at)gmail.com to get an invite.
|
||||
|
||||
## Testing
|
||||
|
||||
AsyncDisplayKit has extensive unit test coverage. You'll need to run `pod install` in the root AsyncDisplayKit directory to set up OCMock.
|
||||
|
||||
10
examples/ASCollectionView/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
examples/ASCollectionView/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Sample.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
3
examples/ASTraitCollection/Podfile
Normal file
3
examples/ASTraitCollection/Podfile
Normal file
@ -0,0 +1,3 @@
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios, '8.0'
|
||||
pod 'AsyncDisplayKit', :path => '../..'
|
||||
379
examples/ASTraitCollection/Sample.xcodeproj/project.pbxproj
Normal file
379
examples/ASTraitCollection/Sample.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,379 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
05E2128719D4DB510098F589 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E2128619D4DB510098F589 /* main.m */; };
|
||||
05E2128A19D4DB510098F589 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E2128919D4DB510098F589 /* AppDelegate.m */; };
|
||||
05E2128D19D4DB510098F589 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E2128C19D4DB510098F589 /* ViewController.m */; };
|
||||
3EC0CDCBA10D483D9F386E5E /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D24B17D1E4A4E7A9566C5E9 /* libPods.a */; };
|
||||
9C37D01E1CC94BC9004C8BC1 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9C37D01D1CC94BC9004C8BC1 /* Launch Screen.storyboard */; };
|
||||
9CACC7811CCEAF9E009A1613 /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CACC7801CCEAF9E009A1613 /* TableViewController.m */; };
|
||||
9CACC7841CCEAFAE009A1613 /* CollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CACC7831CCEAFAE009A1613 /* CollectionViewController.m */; };
|
||||
9CACC7871CCEBD3B009A1613 /* KittenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CACC7861CCEBD3B009A1613 /* KittenNode.m */; };
|
||||
9CACC78A1CCEC82C009A1613 /* OverrideViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CACC7891CCEC82C009A1613 /* OverrideViewController.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
05E2128119D4DB510098F589 /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
05E2128519D4DB510098F589 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
05E2128619D4DB510098F589 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
05E2128819D4DB510098F589 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
05E2128919D4DB510098F589 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
05E2128B19D4DB510098F589 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
||||
05E2128C19D4DB510098F589 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
||||
088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
|
||||
3D24B17D1E4A4E7A9566C5E9 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9C37D01D1CC94BC9004C8BC1 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
|
||||
9CACC77F1CCEAF9E009A1613 /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = "<group>"; };
|
||||
9CACC7801CCEAF9E009A1613 /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = "<group>"; };
|
||||
9CACC7821CCEAFAE009A1613 /* CollectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionViewController.h; sourceTree = "<group>"; };
|
||||
9CACC7831CCEAFAE009A1613 /* CollectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CollectionViewController.m; sourceTree = "<group>"; };
|
||||
9CACC7851CCEBD3B009A1613 /* KittenNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KittenNode.h; sourceTree = "<group>"; };
|
||||
9CACC7861CCEBD3B009A1613 /* KittenNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KittenNode.m; sourceTree = "<group>"; };
|
||||
9CACC7881CCEC82C009A1613 /* OverrideViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OverrideViewController.h; sourceTree = "<group>"; };
|
||||
9CACC7891CCEC82C009A1613 /* OverrideViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OverrideViewController.m; sourceTree = "<group>"; };
|
||||
C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
05E2127E19D4DB510098F589 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3EC0CDCBA10D483D9F386E5E /* libPods.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
05E2127819D4DB510098F589 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E2128319D4DB510098F589 /* Sample */,
|
||||
05E2128219D4DB510098F589 /* Products */,
|
||||
1A943BF0259746F18D6E423F /* Frameworks */,
|
||||
1AE410B73DA5C3BD087ACDD7 /* Pods */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 0;
|
||||
};
|
||||
05E2128219D4DB510098F589 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E2128119D4DB510098F589 /* Sample.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05E2128319D4DB510098F589 /* Sample */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E2128819D4DB510098F589 /* AppDelegate.h */,
|
||||
05E2128919D4DB510098F589 /* AppDelegate.m */,
|
||||
05E2128B19D4DB510098F589 /* ViewController.h */,
|
||||
05E2128C19D4DB510098F589 /* ViewController.m */,
|
||||
05E2128419D4DB510098F589 /* Supporting Files */,
|
||||
9CACC77F1CCEAF9E009A1613 /* TableViewController.h */,
|
||||
9CACC7801CCEAF9E009A1613 /* TableViewController.m */,
|
||||
9CACC7821CCEAFAE009A1613 /* CollectionViewController.h */,
|
||||
9CACC7831CCEAFAE009A1613 /* CollectionViewController.m */,
|
||||
9CACC7851CCEBD3B009A1613 /* KittenNode.h */,
|
||||
9CACC7861CCEBD3B009A1613 /* KittenNode.m */,
|
||||
9CACC7881CCEC82C009A1613 /* OverrideViewController.h */,
|
||||
9CACC7891CCEC82C009A1613 /* OverrideViewController.m */,
|
||||
);
|
||||
path = Sample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05E2128419D4DB510098F589 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E2128519D4DB510098F589 /* Info.plist */,
|
||||
05E2128619D4DB510098F589 /* main.m */,
|
||||
9C37D01D1CC94BC9004C8BC1 /* Launch Screen.storyboard */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1A943BF0259746F18D6E423F /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3D24B17D1E4A4E7A9566C5E9 /* libPods.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1AE410B73DA5C3BD087ACDD7 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */,
|
||||
088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
05E2128019D4DB510098F589 /* Sample */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 05E212A419D4DB510098F589 /* Build configuration list for PBXNativeTarget "Sample" */;
|
||||
buildPhases = (
|
||||
E080B80F89C34A25B3488E26 /* Check Pods Manifest.lock */,
|
||||
05E2127D19D4DB510098F589 /* Sources */,
|
||||
05E2127E19D4DB510098F589 /* Frameworks */,
|
||||
05E2127F19D4DB510098F589 /* Resources */,
|
||||
F012A6F39E0149F18F564F50 /* Copy Pods Resources */,
|
||||
FFF65E837E66ADA71296F0FF /* Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Sample;
|
||||
productName = Sample;
|
||||
productReference = 05E2128119D4DB510098F589 /* Sample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
05E2127919D4DB510098F589 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0600;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
05E2128019D4DB510098F589 = {
|
||||
CreatedOnToolsVersion = 6.0.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 05E2127C19D4DB510098F589 /* Build configuration list for PBXProject "Sample" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 05E2127819D4DB510098F589;
|
||||
productRefGroup = 05E2128219D4DB510098F589 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
05E2128019D4DB510098F589 /* Sample */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
05E2127F19D4DB510098F589 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9C37D01E1CC94BC9004C8BC1 /* Launch Screen.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
E080B80F89C34A25B3488E26 /* Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F012A6F39E0149F18F564F50 /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FFF65E837E66ADA71296F0FF /* Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
05E2127D19D4DB510098F589 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
05E2128D19D4DB510098F589 /* ViewController.m in Sources */,
|
||||
9CACC78A1CCEC82C009A1613 /* OverrideViewController.m in Sources */,
|
||||
05E2128A19D4DB510098F589 /* AppDelegate.m in Sources */,
|
||||
05E2128719D4DB510098F589 /* main.m in Sources */,
|
||||
9CACC7841CCEAFAE009A1613 /* CollectionViewController.m in Sources */,
|
||||
9CACC7871CCEBD3B009A1613 /* KittenNode.m in Sources */,
|
||||
9CACC7811CCEAF9E009A1613 /* TableViewController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
05E212A219D4DB510098F589 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
05E212A319D4DB510098F589 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
05E212A519D4DB510098F589 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
INFOPLIST_FILE = Sample/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
05E212A619D4DB510098F589 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */;
|
||||
buildSettings = {
|
||||
INFOPLIST_FILE = Sample/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
05E2127C19D4DB510098F589 /* Build configuration list for PBXProject "Sample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
05E212A219D4DB510098F589 /* Debug */,
|
||||
05E212A319D4DB510098F589 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
05E212A419D4DB510098F589 /* Build configuration list for PBXNativeTarget "Sample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
05E212A519D4DB510098F589 /* Debug */,
|
||||
05E212A619D4DB510098F589 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 05E2127919D4DB510098F589 /* Project object */;
|
||||
}
|
||||
7
examples/ASTraitCollection/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
examples/ASTraitCollection/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Sample.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0620"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
10
examples/ASTraitCollection/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
examples/ASTraitCollection/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Sample.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
20
examples/ASTraitCollection/Sample/AppDelegate.h
Normal file
20
examples/ASTraitCollection/Sample/AppDelegate.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define UseAutomaticLayout 1
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
31
examples/ASTraitCollection/Sample/AppDelegate.m
Normal file
31
examples/ASTraitCollection/Sample/AppDelegate.m
Normal file
@ -0,0 +1,31 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "ViewController.h"
|
||||
#import "TableViewController.h"
|
||||
#import "CollectionViewController.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
self.window.backgroundColor = [UIColor whiteColor];
|
||||
UITabBarController *tabController = [[UITabBarController alloc] init];
|
||||
[tabController setViewControllers:@[[[ViewController alloc] init], [[TableViewController alloc] init], [[CollectionViewController alloc] init]]];
|
||||
self.window.rootViewController = tabController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
15
examples/ASTraitCollection/Sample/CollectionViewController.h
Normal file
15
examples/ASTraitCollection/Sample/CollectionViewController.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@interface CollectionViewController : ASViewController<ASCollectionNode *>
|
||||
@end
|
||||
73
examples/ASTraitCollection/Sample/CollectionViewController.m
Normal file
73
examples/ASTraitCollection/Sample/CollectionViewController.m
Normal file
@ -0,0 +1,73 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "CollectionViewController.h"
|
||||
#import "KittenNode.h"
|
||||
#import <AsyncDisplayKit/ASTraitCollection.h>
|
||||
|
||||
@interface CollectionViewController () <ASCollectionDelegate, ASCollectionDataSource>
|
||||
@property (nonatomic, strong) ASCollectionNode *collectionNode;
|
||||
@end
|
||||
|
||||
@implementation CollectionViewController
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||
layout.minimumLineSpacing = 10;
|
||||
layout.minimumInteritemSpacing = 10;
|
||||
|
||||
ASCollectionNode *collectionNode = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout];
|
||||
|
||||
if (!(self = [super initWithNode:collectionNode]))
|
||||
return nil;
|
||||
|
||||
self.title = @"Collection Node";
|
||||
_collectionNode = collectionNode;
|
||||
collectionNode.dataSource = self;
|
||||
collectionNode.delegate = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
self.collectionNode.view.contentInset = UIEdgeInsetsMake(20, 10, CGRectGetHeight(self.tabBarController.tabBar.frame), 10);
|
||||
}
|
||||
|
||||
#pragma mark - ASCollectionDataSource
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
KittenNode *cell = [[KittenNode alloc] init];
|
||||
cell.textNode.maximumNumberOfLines = 3;
|
||||
cell.imageTappedBlock = ^{
|
||||
[KittenNode defaultImageTappedAction:self];
|
||||
};
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
ASTraitCollection *traitCollection = [self.collectionNode asyncTraitCollection];
|
||||
|
||||
if (traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) {
|
||||
return ASSizeRangeMake(CGSizeMake(200, 120), CGSizeMake(200, 120));
|
||||
}
|
||||
return ASSizeRangeMake(CGSizeMake(132, 180), CGSizeMake(132, 180));
|
||||
}
|
||||
|
||||
@end
|
||||
39
examples/ASTraitCollection/Sample/Info.plist
Normal file
39
examples/ASTraitCollection/Sample/Info.plist
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>Launch Screen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
23
examples/ASTraitCollection/Sample/KittenNode.h
Normal file
23
examples/ASTraitCollection/Sample/KittenNode.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@interface KittenNode : ASCellNode
|
||||
@property (nonatomic, strong, readonly) ASNetworkImageNode *imageNode;
|
||||
@property (nonatomic, strong, readonly) ASTextNode *textNode;
|
||||
|
||||
@property (nonatomic, copy) dispatch_block_t imageTappedBlock;
|
||||
|
||||
// The default action when an image node is tapped. This action will create an
|
||||
// OverrideVC and override its display traits to always be compact.
|
||||
+ (void)defaultImageTappedAction:(ASViewController *)sourceViewController;
|
||||
@end
|
||||
170
examples/ASTraitCollection/Sample/KittenNode.m
Normal file
170
examples/ASTraitCollection/Sample/KittenNode.m
Normal file
@ -0,0 +1,170 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "KittenNode.h"
|
||||
#import "OverrideViewController.h"
|
||||
|
||||
#import <AsyncDisplayKit/ASTraitCollection.h>
|
||||
|
||||
static const CGFloat kOuterPadding = 16.0f;
|
||||
static const CGFloat kInnerPadding = 10.0f;
|
||||
|
||||
@interface KittenNode ()
|
||||
{
|
||||
CGSize _kittenSize;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation KittenNode
|
||||
|
||||
// lorem ipsum text courtesy https://kittyipsum.com/ <3
|
||||
+ (NSArray *)placeholders
|
||||
{
|
||||
static NSArray *placeholders = nil;
|
||||
|
||||
static dispatch_once_t once;
|
||||
dispatch_once(&once, ^{
|
||||
placeholders = @[
|
||||
@"Kitty ipsum dolor sit amet, purr sleep on your face lay down in your way biting, sniff tincidunt a etiam fluffy fur judging you stuck in a tree kittens.",
|
||||
@"Lick tincidunt a biting eat the grass, egestas enim ut lick leap puking climb the curtains lick.",
|
||||
@"Lick quis nunc toss the mousie vel, tortor pellentesque sunbathe orci turpis non tail flick suscipit sleep in the sink.",
|
||||
@"Orci turpis litter box et stuck in a tree, egestas ac tempus et aliquam elit.",
|
||||
@"Hairball iaculis dolor dolor neque, nibh adipiscing vehicula egestas dolor aliquam.",
|
||||
@"Sunbathe fluffy fur tortor faucibus pharetra jump, enim jump on the table I don't like that food catnip toss the mousie scratched.",
|
||||
@"Quis nunc nam sleep in the sink quis nunc purr faucibus, chase the red dot consectetur bat sagittis.",
|
||||
@"Lick tail flick jump on the table stretching purr amet, rhoncus scratched jump on the table run.",
|
||||
@"Suspendisse aliquam vulputate feed me sleep on your keyboard, rip the couch faucibus sleep on your keyboard tristique give me fish dolor.",
|
||||
@"Rip the couch hiss attack your ankles biting pellentesque puking, enim suspendisse enim mauris a.",
|
||||
@"Sollicitudin iaculis vestibulum toss the mousie biting attack your ankles, puking nunc jump adipiscing in viverra.",
|
||||
@"Nam zzz amet neque, bat tincidunt a iaculis sniff hiss bibendum leap nibh.",
|
||||
@"Chase the red dot enim puking chuf, tristique et egestas sniff sollicitudin pharetra enim ut mauris a.",
|
||||
@"Sagittis scratched et lick, hairball leap attack adipiscing catnip tail flick iaculis lick.",
|
||||
@"Neque neque sleep in the sink neque sleep on your face, climb the curtains chuf tail flick sniff tortor non.",
|
||||
@"Ac etiam kittens claw toss the mousie jump, pellentesque rhoncus litter box give me fish adipiscing mauris a.",
|
||||
@"Pharetra egestas sunbathe faucibus ac fluffy fur, hiss feed me give me fish accumsan.",
|
||||
@"Tortor leap tristique accumsan rutrum sleep in the sink, amet sollicitudin adipiscing dolor chase the red dot.",
|
||||
@"Knock over the lamp pharetra vehicula sleep on your face rhoncus, jump elit cras nec quis quis nunc nam.",
|
||||
@"Sollicitudin feed me et ac in viverra catnip, nunc eat I don't like that food iaculis give me fish.",
|
||||
];
|
||||
});
|
||||
|
||||
return placeholders;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
_kittenSize = CGSizeMake(100,100);
|
||||
|
||||
// kitten image, with a solid background colour serving as placeholder
|
||||
_imageNode = [[ASNetworkImageNode alloc] init];
|
||||
_imageNode.backgroundColor = ASDisplayNodeDefaultPlaceholderColor();
|
||||
_imageNode.preferredFrameSize = _kittenSize;
|
||||
[_imageNode addTarget:self action:@selector(imageTapped:) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
|
||||
CGFloat scale = [UIScreen mainScreen].scale;
|
||||
_imageNode.URL = [NSURL URLWithString:[NSString stringWithFormat:@"https://placekitten.com/%zd/%zd?image=%zd",
|
||||
(NSInteger)roundl(_kittenSize.width * scale),
|
||||
(NSInteger)roundl(_kittenSize.height * scale),
|
||||
(NSInteger)arc4random_uniform(20)]];
|
||||
[self addSubnode:_imageNode];
|
||||
|
||||
// lorem ipsum text, plus some nice styling
|
||||
_textNode = [[ASTextNode alloc] init];
|
||||
_textNode.attributedString = [[NSAttributedString alloc] initWithString:[self kittyIpsum]
|
||||
attributes:[self textStyle]];
|
||||
_textNode.flexShrink = YES;
|
||||
_textNode.flexGrow = YES;
|
||||
[self addSubnode:_textNode];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)imageTapped:(id)sender
|
||||
{
|
||||
if (self.imageTappedBlock) {
|
||||
self.imageTappedBlock();
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)kittyIpsum
|
||||
{
|
||||
NSArray *placeholders = [KittenNode placeholders];
|
||||
u_int32_t ipsumCount = (u_int32_t)[placeholders count];
|
||||
u_int32_t location = arc4random_uniform(ipsumCount);
|
||||
u_int32_t length = arc4random_uniform(ipsumCount - location);
|
||||
|
||||
NSMutableString *string = [placeholders[location] mutableCopy];
|
||||
for (u_int32_t i = location + 1; i < location + length; i++) {
|
||||
[string appendString:(i % 2 == 0) ? @"\n" : @" "];
|
||||
[string appendString:placeholders[i]];
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
- (NSDictionary *)textStyle
|
||||
{
|
||||
UIFont *font = [UIFont fontWithName:@"HelveticaNeue" size:12.0f];
|
||||
|
||||
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||
style.paragraphSpacing = 0.5 * font.lineHeight;
|
||||
style.hyphenationFactor = 1.0;
|
||||
|
||||
return @{ NSFontAttributeName: font,
|
||||
NSParagraphStyleAttributeName: style,
|
||||
ASTextNodeWordKerningAttributeName : @.5};
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
ASTraitCollection *traitCollection = [self asyncTraitCollection];
|
||||
|
||||
ASStackLayoutSpec *stackSpec = [[ASStackLayoutSpec alloc] init];
|
||||
stackSpec.spacing = kInnerPadding;
|
||||
stackSpec.children = @[_imageNode, _textNode];
|
||||
|
||||
if (traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) {
|
||||
_imageNode.alignSelf = ASStackLayoutAlignSelfStart;
|
||||
stackSpec.direction = ASStackLayoutDirectionHorizontal;
|
||||
} else {
|
||||
_imageNode.alignSelf = ASStackLayoutAlignSelfCenter;
|
||||
stackSpec.direction = ASStackLayoutDirectionVertical;
|
||||
}
|
||||
|
||||
return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(kOuterPadding, kOuterPadding, kOuterPadding, kOuterPadding) child:stackSpec];
|
||||
}
|
||||
|
||||
+ (void)defaultImageTappedAction:(ASViewController *)sourceViewController
|
||||
{
|
||||
OverrideViewController *overrideVC = [[OverrideViewController alloc] init];
|
||||
|
||||
overrideVC.overrideDisplayTraitsWithTraitCollection = ^(UITraitCollection *traitCollection) {
|
||||
ASTraitCollection *asyncTraitCollection = [ASTraitCollection traitCollectionWithDisplayScale:traitCollection.displayScale
|
||||
userInterfaceIdiom:traitCollection.userInterfaceIdiom
|
||||
horizontalSizeClass:UIUserInterfaceSizeClassCompact
|
||||
verticalSizeClass:UIUserInterfaceSizeClassCompact
|
||||
forceTouchCapability:traitCollection.forceTouchCapability
|
||||
traitCollectionContext:nil];
|
||||
return asyncTraitCollection;
|
||||
};
|
||||
|
||||
[sourceViewController presentViewController:overrideVC animated:YES completion:nil];
|
||||
overrideVC.closeBlock = ^{
|
||||
[sourceViewController dismissViewControllerAnimated:YES completion:nil];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
50
examples/ASTraitCollection/Sample/Launch Screen.storyboard
Normal file
50
examples/ASTraitCollection/Sample/Launch Screen.storyboard
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright © 2016 Facebook. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
|
||||
<rect key="frame" x="20" y="559" width="560" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display Traits" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
|
||||
<rect key="frame" x="20" y="180" width="560" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/>
|
||||
<constraint firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
|
||||
<constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" constant="20" symbolic="YES" id="SfN-ll-jLj"/>
|
||||
<constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/>
|
||||
<constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
|
||||
<constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" constant="20" symbolic="YES" id="x7j-FC-K8j"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="625" y="488"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
29
examples/ASTraitCollection/Sample/OverrideViewController.h
Normal file
29
examples/ASTraitCollection/Sample/OverrideViewController.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
/*
|
||||
* A simple node that displays the attribution for the kitties in the app. Note that
|
||||
* for a regular horizontal size class it does something stupid and sets the font size to 100.
|
||||
* It's VC, OverrideViewController, will have its display traits overridden such that
|
||||
* it will always have a compact horizontal size class.
|
||||
*/
|
||||
@interface OverrideNode : ASDisplayNode
|
||||
@end
|
||||
|
||||
/*
|
||||
* This is a fairly stupid VC that's main purpose is to show how to override ASDisplayTraits.
|
||||
* Take a look at `defaultImageTappedAction` in KittenNode to see how this is accomplished.
|
||||
*/
|
||||
@interface OverrideViewController : ASViewController<OverrideNode *>
|
||||
@property (nonatomic, copy) dispatch_block_t closeBlock;
|
||||
@end
|
||||
97
examples/ASTraitCollection/Sample/OverrideViewController.m
Normal file
97
examples/ASTraitCollection/Sample/OverrideViewController.m
Normal file
@ -0,0 +1,97 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "OverrideViewController.h"
|
||||
#import <AsyncDisplayKit/ASTraitCollection.h>
|
||||
|
||||
static NSString *kLinkAttributeName = @"PlaceKittenNodeLinkAttributeName";
|
||||
|
||||
@interface OverrideNode()
|
||||
@property (nonatomic, strong) ASTextNode *textNode;
|
||||
@property (nonatomic, strong) ASButtonNode *buttonNode;
|
||||
@end
|
||||
|
||||
@implementation OverrideNode
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
_textNode = [[ASTextNode alloc] init];
|
||||
_textNode.flexGrow = YES;
|
||||
_textNode.flexShrink = YES;
|
||||
_textNode.maximumNumberOfLines = 3;
|
||||
[self addSubnode:_textNode];
|
||||
|
||||
_buttonNode = [[ASButtonNode alloc] init];
|
||||
[_buttonNode setAttributedTitle:[[NSAttributedString alloc] initWithString:@"Close"] forState:ASControlStateNormal];
|
||||
[self addSubnode:_buttonNode];
|
||||
|
||||
self.backgroundColor = [UIColor lightGrayColor];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
CGFloat pointSize = 16.f;
|
||||
ASTraitCollection *traitCollection = [self asyncTraitCollection];
|
||||
if (traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) {
|
||||
// This should never happen because we override the VC's display traits to always be compact.
|
||||
pointSize = 100;
|
||||
}
|
||||
|
||||
NSString *blurb = @"kittens courtesy placekitten.com";
|
||||
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:blurb];
|
||||
[string addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"HelveticaNeue" size:pointSize] range:NSMakeRange(0, blurb.length)];
|
||||
[string addAttributes:@{
|
||||
kLinkAttributeName: [NSURL URLWithString:@"http://placekitten.com/"],
|
||||
NSForegroundColorAttributeName: [UIColor grayColor],
|
||||
NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle | NSUnderlinePatternDot),
|
||||
}
|
||||
range:[blurb rangeOfString:@"placekitten.com"]];
|
||||
|
||||
_textNode.attributedString = string;
|
||||
|
||||
ASStackLayoutSpec *stackSpec = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
stackSpec.children = @[_textNode, _buttonNode];
|
||||
stackSpec.spacing = 10;
|
||||
return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(40, 20, 20, 20) child:stackSpec];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface OverrideViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation OverrideViewController
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
OverrideNode *overrideNode = [[OverrideNode alloc] init];
|
||||
|
||||
if (!(self = [super initWithNode:overrideNode]))
|
||||
return nil;
|
||||
|
||||
[overrideNode.buttonNode addTarget:self action:@selector(closeTapped:) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)closeTapped:(id)sender
|
||||
{
|
||||
if (self.closeBlock) {
|
||||
self.closeBlock();
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
16
examples/ASTraitCollection/Sample/TableViewController.h
Normal file
16
examples/ASTraitCollection/Sample/TableViewController.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@interface TableViewController : ASViewController<ASTableNode *>
|
||||
|
||||
@end
|
||||
62
examples/ASTraitCollection/Sample/TableViewController.m
Normal file
62
examples/ASTraitCollection/Sample/TableViewController.m
Normal file
@ -0,0 +1,62 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "TableViewController.h"
|
||||
#import "KittenNode.h"
|
||||
|
||||
@interface TableViewController () <ASTableViewDataSource, ASTableViewDelegate>
|
||||
@property (nonatomic, strong) ASTableNode *tableNode;
|
||||
@end
|
||||
|
||||
@implementation TableViewController
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
ASTableNode *tableNode = [[ASTableNode alloc] init];
|
||||
if (!(self = [super initWithNode:tableNode]))
|
||||
return nil;
|
||||
|
||||
_tableNode = tableNode;
|
||||
tableNode.delegate = self;
|
||||
tableNode.dataSource = self;
|
||||
self.title = @"Table Node";
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
self.tableNode.view.contentInset = UIEdgeInsetsMake(CGRectGetHeight([[UIApplication sharedApplication] statusBarFrame]), 0, CGRectGetHeight(self.tabBarController.tabBar.frame), 0);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark ASTableView.
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
}
|
||||
|
||||
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
KittenNode *cell = [[KittenNode alloc] init];
|
||||
cell.imageTappedBlock = ^{
|
||||
[KittenNode defaultImageTappedAction:self];
|
||||
};
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
|
||||
@end
|
||||
16
examples/ASTraitCollection/Sample/ViewController.h
Normal file
16
examples/ASTraitCollection/Sample/ViewController.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@interface ViewController : ASViewController<ASDisplayNode *>
|
||||
|
||||
@end
|
||||
45
examples/ASTraitCollection/Sample/ViewController.m
Normal file
45
examples/ASTraitCollection/Sample/ViewController.m
Normal file
@ -0,0 +1,45 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "ViewController.h"
|
||||
#import "KittenNode.h"
|
||||
#import "OverrideViewController.h"
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
#import <AsyncDisplayKit/ASAssert.h>
|
||||
|
||||
@interface ViewController ()
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark UIViewController.
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
KittenNode *displayNode = [[KittenNode alloc] init];
|
||||
if (!(self = [super initWithNode:displayNode]))
|
||||
return nil;
|
||||
|
||||
self.title = @"Display Node";
|
||||
displayNode.imageTappedBlock = ^{
|
||||
[KittenNode defaultImageTappedAction:self];
|
||||
};
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewWillLayoutSubviews
|
||||
{
|
||||
[super viewWillLayoutSubviews];
|
||||
}
|
||||
|
||||
@end
|
||||
20
examples/ASTraitCollection/Sample/main.m
Normal file
20
examples/ASTraitCollection/Sample/main.m
Normal file
@ -0,0 +1,20 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
@ -24,8 +24,8 @@ final class ViewController: ASViewController, ASCollectionDelegate, ASCollection
|
||||
layout.minimumInteritemSpacing = padding
|
||||
layout.minimumLineSpacing = padding
|
||||
super.init(node: ASCollectionNode(collectionViewLayout: layout))
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Color", style: .Plain, target: self, action: "didTapColorsButton")
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Layout", style: .Plain, target: self, action: "didTapLayoutButton")
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Color", style: .Plain, target: self, action: #selector(didTapColorsButton))
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Layout", style: .Plain, target: self, action: #selector(didTapLayoutButton))
|
||||
collectionNode.delegate = self
|
||||
collectionNode.dataSource = self
|
||||
title = "Background Updating"
|
||||
|
||||
@ -10,101 +10,125 @@
|
||||
*/
|
||||
|
||||
#import "ViewController.h"
|
||||
#import "ASLayoutSpec.h"
|
||||
#import "ASStaticLayoutSpec.h"
|
||||
|
||||
@interface ViewController()<ASVideoNodeDelegate>
|
||||
@property (nonatomic, strong) ASDisplayNode *rootNode;
|
||||
@property (nonatomic, strong) ASVideoNode *guitarVideoNode;
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
|
||||
#pragma mark - UIViewController
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
[self.view addSubnode:self.guitarVideoNode];
|
||||
// Root node for the view controller
|
||||
_rootNode = [ASDisplayNode new];
|
||||
_rootNode.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
ASVideoNode *nicCageVideo = [self nicCageVideo];
|
||||
[self.view addSubnode:nicCageVideo];
|
||||
ASVideoNode *guitarVideoNode = self.guitarVideoNode;
|
||||
[_rootNode addSubnode:self.guitarVideoNode];
|
||||
|
||||
ASVideoNode *simonVideo = [self simonVideo];
|
||||
[self.view addSubnode:simonVideo];
|
||||
ASVideoNode *nicCageVideoNode = self.nicCageVideoNode;
|
||||
[_rootNode addSubnode:nicCageVideoNode];
|
||||
|
||||
// Video node with custom play button
|
||||
ASVideoNode *simonVideoNode = self.simonVideoNode;
|
||||
simonVideoNode.playButton = self.playButton;
|
||||
[_rootNode addSubnode:simonVideoNode];
|
||||
|
||||
_rootNode.layoutSpecBlock = ^ASLayoutSpec *(ASDisplayNode * _Nonnull node, ASSizeRange constrainedSize) {
|
||||
guitarVideoNode.layoutPosition = CGPointMake(0, 0);
|
||||
guitarVideoNode.preferredFrameSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height/3);
|
||||
|
||||
nicCageVideoNode.layoutPosition = CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/3);
|
||||
nicCageVideoNode.preferredFrameSize = CGSizeMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/3);
|
||||
|
||||
simonVideoNode.layoutPosition = CGPointMake(0, [UIScreen mainScreen].bounds.size.height - ([UIScreen mainScreen].bounds.size.height/3));
|
||||
simonVideoNode.preferredFrameSize = CGSizeMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/3);
|
||||
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[guitarVideoNode, nicCageVideoNode, simonVideoNode]];
|
||||
};
|
||||
[self.view addSubnode:_rootNode];
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
[super viewDidLayoutSubviews];
|
||||
|
||||
// After all subviews are layed out we have to measure it and move the root node to the right place
|
||||
CGSize viewSize = self.view.bounds.size;
|
||||
[self.rootNode measureWithSizeRange:ASSizeRangeMake(viewSize, viewSize)];
|
||||
[self.rootNode setNeedsLayout];
|
||||
}
|
||||
|
||||
#pragma mark - Getter / Setter
|
||||
|
||||
- (ASVideoNode *)guitarVideoNode;
|
||||
{
|
||||
if (_guitarVideoNode) {
|
||||
return _guitarVideoNode;
|
||||
}
|
||||
|
||||
_guitarVideoNode = [[ASVideoNode alloc] init];
|
||||
|
||||
_guitarVideoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"https://files.parsetfss.com/8a8a3b0c-619e-4e4d-b1d5-1b5ba9bf2b42/tfss-3045b261-7e93-4492-b7e5-5d6358376c9f-editedLiveAndDie.mov"]];
|
||||
|
||||
_guitarVideoNode.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height/3);
|
||||
|
||||
_guitarVideoNode.gravity = AVLayerVideoGravityResizeAspectFill;
|
||||
|
||||
_guitarVideoNode.backgroundColor = [UIColor lightGrayColor];
|
||||
|
||||
_guitarVideoNode.periodicTimeObserverTimescale = 1; //Default is 100
|
||||
|
||||
_guitarVideoNode.delegate = self;
|
||||
|
||||
return _guitarVideoNode;
|
||||
}
|
||||
|
||||
- (ASVideoNode *)nicCageVideo;
|
||||
- (ASVideoNode *)nicCageVideoNode;
|
||||
{
|
||||
ASVideoNode *nicCageVideo = [[ASVideoNode alloc] init];
|
||||
ASVideoNode *nicCageVideoNode = [[ASVideoNode alloc] init];
|
||||
nicCageVideoNode.delegate = self;
|
||||
nicCageVideoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"https://files.parsetfss.com/8a8a3b0c-619e-4e4d-b1d5-1b5ba9bf2b42/tfss-753fe655-86bb-46da-89b7-aa59c60e49c0-niccage.mp4"]];
|
||||
nicCageVideoNode.gravity = AVLayerVideoGravityResize;
|
||||
nicCageVideoNode.backgroundColor = [UIColor lightGrayColor];
|
||||
nicCageVideoNode.shouldAutorepeat = YES;
|
||||
nicCageVideoNode.shouldAutoplay = YES;
|
||||
nicCageVideoNode.muted = YES;
|
||||
|
||||
nicCageVideo.delegate = self;
|
||||
|
||||
nicCageVideo.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"https://files.parsetfss.com/8a8a3b0c-619e-4e4d-b1d5-1b5ba9bf2b42/tfss-753fe655-86bb-46da-89b7-aa59c60e49c0-niccage.mp4"]];
|
||||
|
||||
nicCageVideo.frame = CGRectMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/3, [UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/3);
|
||||
|
||||
nicCageVideo.gravity = AVLayerVideoGravityResize;
|
||||
|
||||
nicCageVideo.backgroundColor = [UIColor lightGrayColor];
|
||||
nicCageVideo.shouldAutorepeat = YES;
|
||||
nicCageVideo.shouldAutoplay = YES;
|
||||
nicCageVideo.muted = YES;
|
||||
|
||||
return nicCageVideo;
|
||||
return nicCageVideoNode;
|
||||
}
|
||||
|
||||
- (ASVideoNode *)simonVideo;
|
||||
- (ASVideoNode *)simonVideoNode
|
||||
{
|
||||
ASVideoNode *simonVideo = [[ASVideoNode alloc] init];
|
||||
ASVideoNode *simonVideoNode = [[ASVideoNode alloc] init];
|
||||
|
||||
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"simon" ofType:@"mp4"]];
|
||||
simonVideo.asset = [AVAsset assetWithURL:url];
|
||||
simonVideoNode.asset = [AVAsset assetWithURL:url];
|
||||
simonVideoNode.gravity = AVLayerVideoGravityResizeAspect;
|
||||
simonVideoNode.backgroundColor = [UIColor lightGrayColor];
|
||||
simonVideoNode.shouldAutorepeat = YES;
|
||||
simonVideoNode.shouldAutoplay = YES;
|
||||
simonVideoNode.muted = YES;
|
||||
|
||||
simonVideo.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height - ([UIScreen mainScreen].bounds.size.height/3), [UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/3);
|
||||
|
||||
simonVideo.gravity = AVLayerVideoGravityResizeAspect;
|
||||
|
||||
simonVideo.backgroundColor = [UIColor lightGrayColor];
|
||||
simonVideo.shouldAutorepeat = YES;
|
||||
simonVideo.shouldAutoplay = YES;
|
||||
simonVideo.muted = YES;
|
||||
|
||||
return simonVideo;
|
||||
return simonVideoNode;
|
||||
}
|
||||
|
||||
- (ASButtonNode *)playButton;
|
||||
{
|
||||
ASButtonNode *playButton = [[ASButtonNode alloc] init];
|
||||
ASButtonNode *playButtonNode = [[ASButtonNode alloc] init];
|
||||
|
||||
UIImage *image = [UIImage imageNamed:@"playButton@2x.png"];
|
||||
[playButton setImage:image forState:ASControlStateNormal];
|
||||
[playButton measure:CGSizeMake(50, 50)];
|
||||
playButton.bounds = CGRectMake(0, 0, playButton.calculatedSize.width, playButton.calculatedSize.height);
|
||||
playButton.position = CGPointMake([UIScreen mainScreen].bounds.size.width/4, ([UIScreen mainScreen].bounds.size.height/3)/2);
|
||||
[playButton setImage:[UIImage imageNamed:@"playButtonSelected@2x.png"] forState:ASControlStateHighlighted];
|
||||
[playButtonNode setImage:image forState:ASControlStateNormal];
|
||||
[playButtonNode setImage:[UIImage imageNamed:@"playButtonSelected@2x.png"] forState:ASControlStateHighlighted];
|
||||
|
||||
return playButton;
|
||||
// Change placement of play button if necessary
|
||||
//playButtonNode.contentHorizontalAlignment = ASHorizontalAlignmentStart;
|
||||
//playButtonNode.contentVerticalAlignment = ASVerticalAlignmentCenter;
|
||||
|
||||
return playButtonNode;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)videoNodeWasTapped:(ASVideoNode *)videoNode
|
||||
{
|
||||
if (videoNode == self.guitarVideoNode) {
|
||||
@ -125,6 +149,7 @@
|
||||
}
|
||||
|
||||
#pragma mark - ASVideoNodeDelegate
|
||||
|
||||
- (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toSate
|
||||
{
|
||||
//Ignore nicCageVideo
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user