Merge remote-tracking branch 'facebook/master'

This commit is contained in:
Hannah Troisi 2016-05-15 20:58:16 -07:00
commit ae29cd2721
73 changed files with 2605 additions and 318 deletions

View File

@ -190,7 +190,6 @@
25E327581C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; }; 25E327581C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; };
25E327591C16819500A2170C /* 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, ); }; }; 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 */; }; 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, ); }; }; 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, ); }; }; 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 */; }; 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 */; }; 636EA1A41C7FF4EC00EE152F /* NSArray+Diffing.m in Sources */ = {isa = PBXBuildFile; fileRef = DBC452DA1C5BF64600B16017 /* NSArray+Diffing.m */; };
636EA1A51C7FF4EF00EE152F /* ASDefaultPlayButton.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.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 */; }; 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 */; }; 68355B341CB579B9001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */; };
68355B3A1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */; }; 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 */; }; 68EE0DBE1C1B4ED300BA1B99 /* ASMainSerialQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */; };
68EE0DBF1C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */; }; 68EE0DBF1C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */; };
68EE0DC01C1B4ED300BA1B99 /* 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, ); }; }; 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, ); }; }; 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, ); }; }; 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, ); }; }; 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 */; }; 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, ); }; }; 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, ); }; }; 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, ); }; }; 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 */; }; 9C8221951BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C8221931BA237B80037F19A /* ASStackBaselinePositionedLayout.h */; };
9C8221961BA237B80037F19A /* 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 */; }; 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 */; }; 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, ); }; }; 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, ); }; }; 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 */; }; 9F06E5CD1B4CAF4200F015D8 /* ASCollectionViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */; };
A2763D791CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */; }; A2763D791CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */; };
A2763D7A1CBDD57D00A9ADBD /* 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 */; }; AC7A2C171BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */; };
AC7A2C181BDE11DF0093FE1A /* 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, ); }; }; 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, ); }; }; 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 */; }; 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, ); }; }; 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 */; }; AEEC47E21C20C2DD00EC1693 /* ASVideoNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E01C20C2DD00EC1693 /* ASVideoNode.mm */; };
AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */; }; 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, ); }; }; 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, ); }; }; 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, ); }; }; 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, ); }; }; 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 */; }; B350625D1B0111740018CF92 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943141A1575670030A7D0 /* Photos.framework */; };
B350625E1B0111780018CF92 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943121A1575630030A7D0 /* AssetsLibrary.framework */; }; B350625E1B0111780018CF92 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943121A1575630030A7D0 /* AssetsLibrary.framework */; };
B350625F1B0111800018CF92 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AF195D04C000B7D73C /* Foundation.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, ); }; }; 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 */; }; CC3B20831C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; };
CC3B20841C3F76D600798563 /* 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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 */, 68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */,
0516FA3E1A1563D200B4EBED /* ASMultiplexImageNode.h */, 0516FA3E1A1563D200B4EBED /* ASMultiplexImageNode.h */,
0516FA3F1A1563D200B4EBED /* ASMultiplexImageNode.mm */, 0516FA3F1A1563D200B4EBED /* ASMultiplexImageNode.mm */,
68FC85DC1CE29AB700EDD713 /* ASNavigationController.h */,
68FC85DD1CE29AB700EDD713 /* ASNavigationController.m */,
055B9FA61A1C154B00035D6D /* ASNetworkImageNode.h */, 055B9FA61A1C154B00035D6D /* ASNetworkImageNode.h */,
055B9FA71A1C154B00035D6D /* ASNetworkImageNode.mm */, 055B9FA71A1C154B00035D6D /* ASNetworkImageNode.mm */,
25E327541C16819500A2170C /* ASPagerNode.h */, 25E327541C16819500A2170C /* ASPagerNode.h */,
@ -1072,8 +1103,10 @@
A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.m */, A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.m */,
D785F6601A74327E00291744 /* ASScrollNode.h */, D785F6601A74327E00291744 /* ASScrollNode.h */,
D785F6611A74327E00291744 /* ASScrollNode.m */, D785F6611A74327E00291744 /* ASScrollNode.m */,
68FC85E01CE29B7E00EDD713 /* ASTabBarController.h */,
68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */,
B0F880581BEAEC7500D17647 /* ASTableNode.h */, B0F880581BEAEC7500D17647 /* ASTableNode.h */,
B0F880591BEAEC7500D17647 /* ASTableNode.m */, 9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */,
055F1A3219ABD3E3004DAFF1 /* ASTableView.h */, 055F1A3219ABD3E3004DAFF1 /* ASTableView.h */,
055F1A3319ABD3E3004DAFF1 /* ASTableView.mm */, 055F1A3319ABD3E3004DAFF1 /* ASTableView.mm */,
AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */, AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */,
@ -1082,11 +1115,13 @@
A373200E1C571B050011FC94 /* ASTextNode+Beta.h */, A373200E1C571B050011FC94 /* ASTextNode+Beta.h */,
058D09E0195D050800B7D73C /* ASTextNode.mm */, 058D09E0195D050800B7D73C /* ASTextNode.mm */,
ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */, ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */,
ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */, 9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */,
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */, 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */,
764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */, 764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */,
764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */, 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */,
DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */, DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */,
68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */,
68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */,
92074A5E1CC8B9DD00918F75 /* tvOS */, 92074A5E1CC8B9DD00918F75 /* tvOS */,
058D09E1195D050800B7D73C /* Details */, 058D09E1195D050800B7D73C /* Details */,
058D0A01195D050800B7D73C /* Private */, 058D0A01195D050800B7D73C /* Private */,
@ -1167,6 +1202,7 @@
058D09E1195D050800B7D73C /* Details */ = { 058D09E1195D050800B7D73C /* Details */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */,
058D09E2195D050800B7D73C /* _ASDisplayLayer.h */, 058D09E2195D050800B7D73C /* _ASDisplayLayer.h */,
058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */, 058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */,
058D09E4195D050800B7D73C /* _ASDisplayView.h */, 058D09E4195D050800B7D73C /* _ASDisplayView.h */,
@ -1187,7 +1223,6 @@
05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */, 05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */,
05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */, 05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */,
698548611CA9E025008A345F /* ASEnvironment.h */, 698548611CA9E025008A345F /* ASEnvironment.h */,
698548621CA9E025008A345F /* ASEnvironment.m */,
4640521B1A3F83C40061C0BA /* ASFlowLayoutController.h */, 4640521B1A3F83C40061C0BA /* ASFlowLayoutController.h */,
4640521C1A3F83C40061C0BA /* ASFlowLayoutController.mm */, 4640521C1A3F83C40061C0BA /* ASFlowLayoutController.mm */,
058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */, 058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */,
@ -1226,6 +1261,8 @@
205F0E0D1B371875007741D0 /* UICollectionViewLayout+ASConvenience.h */, 205F0E0D1B371875007741D0 /* UICollectionViewLayout+ASConvenience.h */,
205F0E0E1B371875007741D0 /* UICollectionViewLayout+ASConvenience.m */, 205F0E0E1B371875007741D0 /* UICollectionViewLayout+ASConvenience.m */,
058D09FF195D050800B7D73C /* UIView+ASConvenience.h */, 058D09FF195D050800B7D73C /* UIView+ASConvenience.h */,
9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */,
9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */,
); );
path = Details; path = Details;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1480,6 +1517,7 @@
058D0A82195D060300B7D73C /* ASAssert.h in Headers */, 058D0A82195D060300B7D73C /* ASAssert.h in Headers */,
0516FA3C1A15563400B4EBED /* ASAvailability.h in Headers */, 0516FA3C1A15563400B4EBED /* ASAvailability.h in Headers */,
AEB7B01A1C5962EA00662EF4 /* ASDefaultPlayButton.h in Headers */, AEB7B01A1C5962EA00662EF4 /* ASDefaultPlayButton.h in Headers */,
68FC85E21CE29B7E00EDD713 /* ASTabBarController.h in Headers */,
ACF6ED1A1B17843500DA7C62 /* ASBackgroundLayoutSpec.h in Headers */, ACF6ED1A1B17843500DA7C62 /* ASBackgroundLayoutSpec.h in Headers */,
058D0A83195D060300B7D73C /* ASBaseDefines.h in Headers */, 058D0A83195D060300B7D73C /* ASBaseDefines.h in Headers */,
054963491A1EA066000F8E56 /* ASBasicImageDownloader.h in Headers */, 054963491A1EA066000F8E56 /* ASBasicImageDownloader.h in Headers */,
@ -1495,6 +1533,7 @@
AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */, AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */,
AEEC47E11C20C2DD00EC1693 /* ASVideoNode.h in Headers */, AEEC47E11C20C2DD00EC1693 /* ASVideoNode.h in Headers */,
DE8BEAC11C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */, DE8BEAC11C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */,
68FC85DE1CE29AB700EDD713 /* ASNavigationController.h in Headers */,
205F0E1D1B373A2C007741D0 /* ASCollectionViewLayoutController.h in Headers */, 205F0E1D1B373A2C007741D0 /* ASCollectionViewLayoutController.h in Headers */,
AC3C4A541A113EEC00143C57 /* ASCollectionViewProtocols.h in Headers */, AC3C4A541A113EEC00143C57 /* ASCollectionViewProtocols.h in Headers */,
058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */, 058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */,
@ -1520,9 +1559,11 @@
0587F9BD1A7309ED00AFF0BA /* ASEditableTextNode.h in Headers */, 0587F9BD1A7309ED00AFF0BA /* ASEditableTextNode.h in Headers */,
DE6EA3221C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */, DE6EA3221C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */,
1950C4491A3BB5C1005C8279 /* ASEqualityHelpers.h in Headers */, 1950C4491A3BB5C1005C8279 /* ASEqualityHelpers.h in Headers */,
68FC85E91CE29C7D00EDD713 /* ASVisibilityProtocols.h in Headers */,
257754A81BEE44CD00737CA5 /* ASTextKitContext.h in Headers */, 257754A81BEE44CD00737CA5 /* ASTextKitContext.h in Headers */,
DB55C2611C6408D6004EDCF5 /* _ASTransitionContext.h in Headers */, DB55C2611C6408D6004EDCF5 /* _ASTransitionContext.h in Headers */,
464052221A3F83C40061C0BA /* ASFlowLayoutController.h in Headers */, 464052221A3F83C40061C0BA /* ASFlowLayoutController.h in Headers */,
9C70F2031CDA4EFA007D6C76 /* ASTraitCollection.h in Headers */,
257754AF1BEE44CD00737CA5 /* ASTextKitRenderer+TextChecking.h in Headers */, 257754AF1BEE44CD00737CA5 /* ASTextKitRenderer+TextChecking.h in Headers */,
058D0A57195D05DC00B7D73C /* ASHighlightOverlayLayer.h in Headers */, 058D0A57195D05DC00B7D73C /* ASHighlightOverlayLayer.h in Headers */,
058D0A7C195D05F900B7D73C /* ASImageNode+CGExtras.h in Headers */, 058D0A7C195D05F900B7D73C /* ASImageNode+CGExtras.h in Headers */,
@ -1607,6 +1648,7 @@
B35062481B010EFD0018CF92 /* _AS-objc-internal.h in Headers */, B35062481B010EFD0018CF92 /* _AS-objc-internal.h in Headers */,
69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */, 69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */,
B350623C1B010EFD0018CF92 /* _ASAsyncTransaction.h in Headers */, B350623C1B010EFD0018CF92 /* _ASAsyncTransaction.h in Headers */,
9C70F20D1CDBE9CB007D6C76 /* ASDefaultPlayButton.h in Headers */,
68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */, 68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */,
7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */, 7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */,
B350623F1B010EFD0018CF92 /* _ASAsyncTransactionContainer.h in Headers */, B350623F1B010EFD0018CF92 /* _ASAsyncTransactionContainer.h in Headers */,
@ -1643,6 +1685,7 @@
AC026B701BD57DBF00BBC17E /* _ASHierarchyChangeSet.h in Headers */, AC026B701BD57DBF00BBC17E /* _ASHierarchyChangeSet.h in Headers */,
B35061F31B010EFD0018CF92 /* ASCellNode.h in Headers */, B35061F31B010EFD0018CF92 /* ASCellNode.h in Headers */,
34EFC7631B701CBF00AD841F /* ASCenterLayoutSpec.h in Headers */, 34EFC7631B701CBF00AD841F /* ASCenterLayoutSpec.h in Headers */,
9C70F20C1CDBE9B6007D6C76 /* ASCollectionDataController.h in Headers */,
18C2ED7F1B9B7DE800F627B3 /* ASCollectionNode.h in Headers */, 18C2ED7F1B9B7DE800F627B3 /* ASCollectionNode.h in Headers */,
9C8898BD1C738BB800D6B02E /* ASTextKitFontSizeAdjuster.h in Headers */, 9C8898BD1C738BB800D6B02E /* ASTextKitFontSizeAdjuster.h in Headers */,
B35061F51B010EFD0018CF92 /* ASCollectionView.h in Headers */, B35061F51B010EFD0018CF92 /* ASCollectionView.h in Headers */,
@ -1651,14 +1694,18 @@
CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */, CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */,
92074A621CC8BA1900918F75 /* ASImageNode+tvOS.h in Headers */, 92074A621CC8BA1900918F75 /* ASImageNode+tvOS.h in Headers */,
B35061F71B010EFD0018CF92 /* ASCollectionViewProtocols.h in Headers */, B35061F71B010EFD0018CF92 /* ASCollectionViewProtocols.h in Headers */,
68FC85E31CE29B7E00EDD713 /* ASTabBarController.h in Headers */,
DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */, DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */,
9C70F20F1CDBE9FF007D6C76 /* ASLayoutManager.h in Headers */,
B35061FA1B010EFD0018CF92 /* ASControlNode+Subclasses.h in Headers */, B35061FA1B010EFD0018CF92 /* ASControlNode+Subclasses.h in Headers */,
B35061F81B010EFD0018CF92 /* ASControlNode.h in Headers */, B35061F81B010EFD0018CF92 /* ASControlNode.h in Headers */,
B35062171B010EFD0018CF92 /* ASDataController.h in Headers */, B35062171B010EFD0018CF92 /* ASDataController.h in Headers */,
B35062191B010EFD0018CF92 /* ASDealloc2MainObject.h in Headers */, B35062191B010EFD0018CF92 /* ASDealloc2MainObject.h in Headers */,
34EFC75B1B701BAF00AD841F /* ASDimension.h in Headers */, 34EFC75B1B701BAF00AD841F /* ASDimension.h in Headers */,
68FC85EA1CE29C7D00EDD713 /* ASVisibilityProtocols.h in Headers */,
A37320101C571B740011FC94 /* ASTextNode+Beta.h in Headers */, A37320101C571B740011FC94 /* ASTextNode+Beta.h in Headers */,
DBABFAFC1C6A8D2F0039EA4A /* _ASTransitionContext.h in Headers */, DBABFAFC1C6A8D2F0039EA4A /* _ASTransitionContext.h in Headers */,
9C70F2061CDA4F0C007D6C76 /* ASTraitCollection.h in Headers */,
254C6B801BF94DF4003EC431 /* ASEqualityHashHelpers.h in Headers */, 254C6B801BF94DF4003EC431 /* ASEqualityHashHelpers.h in Headers */,
B350624F1B010EFD0018CF92 /* ASDisplayNode+DebugTiming.h in Headers */, B350624F1B010EFD0018CF92 /* ASDisplayNode+DebugTiming.h in Headers */,
B35061FD1B010EFD0018CF92 /* ASDisplayNode+Subclasses.h in Headers */, B35061FD1B010EFD0018CF92 /* ASDisplayNode+Subclasses.h in Headers */,
@ -1667,6 +1714,7 @@
B35062521B010EFD0018CF92 /* ASDisplayNodeInternal.h in Headers */, B35062521B010EFD0018CF92 /* ASDisplayNodeInternal.h in Headers */,
B35062001B010EFD0018CF92 /* ASEditableTextNode.h in Headers */, B35062001B010EFD0018CF92 /* ASEditableTextNode.h in Headers */,
B350625B1B010F070018CF92 /* ASEqualityHelpers.h in Headers */, B350625B1B010F070018CF92 /* ASEqualityHelpers.h in Headers */,
680346941CE4052A0009FEB4 /* ASNavigationController.h in Headers */,
B350621B1B010EFD0018CF92 /* ASFlowLayoutController.h in Headers */, B350621B1B010EFD0018CF92 /* ASFlowLayoutController.h in Headers */,
B350621D1B010EFD0018CF92 /* ASHighlightOverlayLayer.h in Headers */, B350621D1B010EFD0018CF92 /* ASHighlightOverlayLayer.h in Headers */,
C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */, C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */,
@ -1677,6 +1725,7 @@
B35062021B010EFD0018CF92 /* ASImageNode.h in Headers */, B35062021B010EFD0018CF92 /* ASImageNode.h in Headers */,
B350621F1B010EFD0018CF92 /* ASImageProtocols.h in Headers */, B350621F1B010EFD0018CF92 /* ASImageProtocols.h in Headers */,
430E7C901B4C23F100697A4C /* ASIndexPath.h in Headers */, 430E7C901B4C23F100697A4C /* ASIndexPath.h in Headers */,
9C70F20B1CDBE9A4007D6C76 /* ASDataController+Subclasses.h in Headers */,
34EFC75F1B701C8600AD841F /* ASInsetLayoutSpec.h in Headers */, 34EFC75F1B701C8600AD841F /* ASInsetLayoutSpec.h in Headers */,
34EFC75D1B701BE900AD841F /* ASInternalHelpers.h in Headers */, 34EFC75D1B701BE900AD841F /* ASInternalHelpers.h in Headers */,
34EFC7671B701CD900AD841F /* ASLayout.h in Headers */, 34EFC7671B701CD900AD841F /* ASLayout.h in Headers */,
@ -1712,6 +1761,7 @@
25E327571C16819500A2170C /* ASPagerNode.h in Headers */, 25E327571C16819500A2170C /* ASPagerNode.h in Headers */,
B35062551B010EFD0018CF92 /* ASSentinel.h in Headers */, B35062551B010EFD0018CF92 /* ASSentinel.h in Headers */,
9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */, 9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */,
9C70F20E1CDBE9E5007D6C76 /* NSArray+Diffing.h in Headers */,
9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */, 9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */,
DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */, DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */,
34EFC7701B701CFA00AD841F /* ASStackLayoutDefines.h in Headers */, 34EFC7701B701CFA00AD841F /* ASStackLayoutDefines.h in Headers */,
@ -1955,6 +2005,7 @@
files = ( files = (
058D0A22195D050800B7D73C /* _ASAsyncTransaction.mm in Sources */, 058D0A22195D050800B7D73C /* _ASAsyncTransaction.mm in Sources */,
E55D86321CA8A14000A0C26F /* ASLayoutable.mm in Sources */, E55D86321CA8A14000A0C26F /* ASLayoutable.mm in Sources */,
68FC85E41CE29B7E00EDD713 /* ASTabBarController.m in Sources */,
058D0A23195D050800B7D73C /* _ASAsyncTransactionContainer.m in Sources */, 058D0A23195D050800B7D73C /* _ASAsyncTransactionContainer.m in Sources */,
058D0A24195D050800B7D73C /* _ASAsyncTransactionGroup.m in Sources */, 058D0A24195D050800B7D73C /* _ASAsyncTransactionGroup.m in Sources */,
68355B3A1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m in Sources */, 68355B3A1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m in Sources */,
@ -1982,7 +2033,9 @@
92DD2FE41BF4B97E0074C9DD /* ASMapNode.mm in Sources */, 92DD2FE41BF4B97E0074C9DD /* ASMapNode.mm in Sources */,
DBC452DC1C5BF64600B16017 /* NSArray+Diffing.m in Sources */, DBC452DC1C5BF64600B16017 /* NSArray+Diffing.m in Sources */,
AC3C4A521A1139C100143C57 /* ASCollectionView.mm in Sources */, AC3C4A521A1139C100143C57 /* ASCollectionView.mm in Sources */,
9CFFC6C21CCAC768006A6476 /* ASTableNode.mm in Sources */,
205F0E1E1B373A2C007741D0 /* ASCollectionViewLayoutController.mm in Sources */, 205F0E1E1B373A2C007741D0 /* ASCollectionViewLayoutController.mm in Sources */,
68FC85EB1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */,
058D0A13195D050800B7D73C /* ASControlNode.mm in Sources */, 058D0A13195D050800B7D73C /* ASControlNode.mm in Sources */,
464052211A3F83C40061C0BA /* ASDataController.mm in Sources */, 464052211A3F83C40061C0BA /* ASDataController.mm in Sources */,
B30BF6531C5964B0004FCD53 /* ASLayoutManager.m in Sources */, B30BF6531C5964B0004FCD53 /* ASLayoutManager.m in Sources */,
@ -2007,7 +2060,7 @@
430E7C911B4C23F100697A4C /* ASIndexPath.m in Sources */, 430E7C911B4C23F100697A4C /* ASIndexPath.m in Sources */,
ACF6ED231B17843500DA7C62 /* ASInsetLayoutSpec.mm in Sources */, ACF6ED231B17843500DA7C62 /* ASInsetLayoutSpec.mm in Sources */,
ACF6ED4C1B17847A00DA7C62 /* ASInternalHelpers.mm in Sources */, ACF6ED4C1B17847A00DA7C62 /* ASInternalHelpers.mm in Sources */,
698548651CA9E025008A345F /* ASEnvironment.m in Sources */, 68FC85DF1CE29AB700EDD713 /* ASNavigationController.m in Sources */,
ACF6ED251B17843500DA7C62 /* ASLayout.mm in Sources */, ACF6ED251B17843500DA7C62 /* ASLayout.mm in Sources */,
DB55C2631C6408D6004EDCF5 /* _ASTransitionContext.m in Sources */, DB55C2631C6408D6004EDCF5 /* _ASTransitionContext.m in Sources */,
92074A631CC8BA1900918F75 /* ASImageNode+tvOS.m in Sources */, 92074A631CC8BA1900918F75 /* ASImageNode+tvOS.m in Sources */,
@ -2046,17 +2099,18 @@
ACF6ED521B17847A00DA7C62 /* ASStackUnpositionedLayout.mm in Sources */, ACF6ED521B17847A00DA7C62 /* ASStackUnpositionedLayout.mm in Sources */,
257754A61BEE44CD00737CA5 /* ASTextKitAttributes.mm in Sources */, 257754A61BEE44CD00737CA5 /* ASTextKitAttributes.mm in Sources */,
81EE38501C8E94F000456208 /* ASRunLoopQueue.mm in Sources */, 81EE38501C8E94F000456208 /* ASRunLoopQueue.mm in Sources */,
9C70F2041CDA4EFA007D6C76 /* ASTraitCollection.m in Sources */,
92074A691CC8BADA00918F75 /* ASControlNode+tvOS.m in Sources */, 92074A691CC8BADA00918F75 /* ASControlNode+tvOS.m in Sources */,
ACF6ED321B17843500DA7C62 /* ASStaticLayoutSpec.mm in Sources */, ACF6ED321B17843500DA7C62 /* ASStaticLayoutSpec.mm in Sources */,
AC026B6B1BD57D6F00BBC17E /* ASChangeSetDataController.m in Sources */, AC026B6B1BD57D6F00BBC17E /* ASChangeSetDataController.m in Sources */,
68355B311CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */, 68355B311CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */,
9CFFC6C01CCAC73C006A6476 /* ASViewController.mm in Sources */,
055F1A3519ABD3E3004DAFF1 /* ASTableView.mm in Sources */, 055F1A3519ABD3E3004DAFF1 /* ASTableView.mm in Sources */,
058D0A17195D050800B7D73C /* ASTextNode.mm in Sources */, 058D0A17195D050800B7D73C /* ASTextNode.mm in Sources */,
257754AC1BEE44CD00737CA5 /* ASTextKitRenderer.mm in Sources */, 257754AC1BEE44CD00737CA5 /* ASTextKitRenderer.mm in Sources */,
ACC945AB1BA9E7C1005E1FB8 /* ASViewController.m in Sources */,
B0F8805B1BEAEC7500D17647 /* ASTableNode.m in Sources */,
205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */, 205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */,
257754B21BEE44CD00737CA5 /* ASTextKitShadower.mm in Sources */, 257754B21BEE44CD00737CA5 /* ASTextKitShadower.mm in Sources */,
9CFFC6BE1CCAC52B006A6476 /* ASEnvironment.mm in Sources */,
058D0A21195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m in Sources */, 058D0A21195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m in Sources */,
205F0E101B371875007741D0 /* UICollectionViewLayout+ASConvenience.m in Sources */, 205F0E101B371875007741D0 /* UICollectionViewLayout+ASConvenience.m in Sources */,
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */, CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */,
@ -2109,6 +2163,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
9C70F2091CDABA36007D6C76 /* ASViewController.mm in Sources */,
DE4843DB1C93EAB100A1F33B /* ASDisplayNodeLayoutContext.mm in Sources */, DE4843DB1C93EAB100A1F33B /* ASDisplayNodeLayoutContext.mm in Sources */,
B30BF6541C59D889004FCD53 /* ASLayoutManager.m in Sources */, B30BF6541C59D889004FCD53 /* ASLayoutManager.m in Sources */,
92DD2FE71BF4D0850074C9DD /* ASMapNode.mm in Sources */, 92DD2FE71BF4D0850074C9DD /* ASMapNode.mm in Sources */,
@ -2121,8 +2176,6 @@
B35062421B010EFD0018CF92 /* _ASAsyncTransactionGroup.m in Sources */, B35062421B010EFD0018CF92 /* _ASAsyncTransactionGroup.m in Sources */,
B350624A1B010EFD0018CF92 /* _ASCoreAnimationExtras.mm in Sources */, B350624A1B010EFD0018CF92 /* _ASCoreAnimationExtras.mm in Sources */,
68EE0DC01C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */, 68EE0DC01C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */,
698548661CA9E025008A345F /* ASEnvironment.m in Sources */,
2767E9421BB19BD600EA9B77 /* ASViewController.m in Sources */,
B35062101B010EFD0018CF92 /* _ASDisplayLayer.mm in Sources */, B35062101B010EFD0018CF92 /* _ASDisplayLayer.mm in Sources */,
9C55866B1BD54A1900B50E3A /* ASAsciiArtBoxCreator.m in Sources */, 9C55866B1BD54A1900B50E3A /* ASAsciiArtBoxCreator.m in Sources */,
B35062121B010EFD0018CF92 /* _ASDisplayView.mm in Sources */, B35062121B010EFD0018CF92 /* _ASDisplayView.mm in Sources */,
@ -2134,13 +2187,16 @@
9C8898BC1C738BA800D6B02E /* ASTextKitFontSizeAdjuster.mm in Sources */, 9C8898BC1C738BA800D6B02E /* ASTextKitFontSizeAdjuster.mm in Sources */,
34EFC7621B701CA400AD841F /* ASBackgroundLayoutSpec.mm in Sources */, 34EFC7621B701CA400AD841F /* ASBackgroundLayoutSpec.mm in Sources */,
DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */, DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */,
9C70F2081CDAA3C6007D6C76 /* ASEnvironment.mm in Sources */,
B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */, B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */,
B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */, B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */,
AC47D9421B3B891B00AAEE9D /* ASCellNode.mm in Sources */, AC47D9421B3B891B00AAEE9D /* ASCellNode.mm in Sources */,
34EFC7641B701CC600AD841F /* ASCenterLayoutSpec.mm in Sources */, 34EFC7641B701CC600AD841F /* ASCenterLayoutSpec.mm in Sources */,
18C2ED831B9B7DE800F627B3 /* ASCollectionNode.mm in Sources */, 18C2ED831B9B7DE800F627B3 /* ASCollectionNode.mm in Sources */,
E55D86331CA8A14000A0C26F /* ASLayoutable.mm in Sources */, E55D86331CA8A14000A0C26F /* ASLayoutable.mm in Sources */,
68FC85EC1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */,
68B8A4E41CBDB958007E4543 /* ASWeakProxy.m in Sources */, 68B8A4E41CBDB958007E4543 /* ASWeakProxy.m in Sources */,
9C70F20A1CDBE949007D6C76 /* ASTableNode.mm in Sources */,
69CB62AE1CB8165900024920 /* _ASDisplayViewAccessiblity.mm in Sources */, 69CB62AE1CB8165900024920 /* _ASDisplayViewAccessiblity.mm in Sources */,
B35061F61B010EFD0018CF92 /* ASCollectionView.mm in Sources */, B35061F61B010EFD0018CF92 /* ASCollectionView.mm in Sources */,
509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.mm in Sources */, 509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.mm in Sources */,
@ -2187,6 +2243,7 @@
044285101BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm in Sources */, 044285101BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm in Sources */,
B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */, B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */,
0442850A1BAA63FE00D16268 /* ASBatchFetching.m in Sources */, 0442850A1BAA63FE00D16268 /* ASBatchFetching.m in Sources */,
68FC85E61CE29B9400EDD713 /* ASNavigationController.m in Sources */,
34EFC76F1B701CF700AD841F /* ASRatioLayoutSpec.mm in Sources */, 34EFC76F1B701CF700AD841F /* ASRatioLayoutSpec.mm in Sources */,
254C6B8B1BF94F8A003EC431 /* ASTextKitShadower.mm in Sources */, 254C6B8B1BF94F8A003EC431 /* ASTextKitShadower.mm in Sources */,
34EFC7661B701CD200AD841F /* ASRelativeSize.mm in Sources */, 34EFC7661B701CD200AD841F /* ASRelativeSize.mm in Sources */,
@ -2198,8 +2255,10 @@
34EFC7721B701D0300AD841F /* ASStackLayoutSpec.mm in Sources */, 34EFC7721B701D0300AD841F /* ASStackLayoutSpec.mm in Sources */,
34EFC7761B701D2A00AD841F /* ASStackPositionedLayout.mm in Sources */, 34EFC7761B701D2A00AD841F /* ASStackPositionedLayout.mm in Sources */,
7AB338661C55B3420055FDE8 /* ASRelativeLayoutSpec.mm in Sources */, 7AB338661C55B3420055FDE8 /* ASRelativeLayoutSpec.mm in Sources */,
9C70F2051CDA4F06007D6C76 /* ASTraitCollection.m in Sources */,
34EFC7781B701D3100AD841F /* ASStackUnpositionedLayout.mm in Sources */, 34EFC7781B701D3100AD841F /* ASStackUnpositionedLayout.mm in Sources */,
DE84918E1C8FFF9F003D89E9 /* ASRunLoopQueue.mm in Sources */, DE84918E1C8FFF9F003D89E9 /* ASRunLoopQueue.mm in Sources */,
68FC85E51CE29B7E00EDD713 /* ASTabBarController.m in Sources */,
AC026B6C1BD57D6F00BBC17E /* ASChangeSetDataController.m in Sources */, AC026B6C1BD57D6F00BBC17E /* ASChangeSetDataController.m in Sources */,
34EFC7741B701D0A00AD841F /* ASStaticLayoutSpec.mm in Sources */, 34EFC7741B701D0A00AD841F /* ASStaticLayoutSpec.mm in Sources */,
92074A6A1CC8BADA00918F75 /* ASControlNode+tvOS.m in Sources */, 92074A6A1CC8BADA00918F75 /* ASControlNode+tvOS.m in Sources */,
@ -2207,7 +2266,6 @@
B350620B1B010EFD0018CF92 /* ASTableView.mm in Sources */, B350620B1B010EFD0018CF92 /* ASTableView.mm in Sources */,
B350620E1B010EFD0018CF92 /* ASTextNode.mm in Sources */, B350620E1B010EFD0018CF92 /* ASTextNode.mm in Sources */,
68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */, 68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */,
C78F7E2A1BF7808300CDEAFC /* ASTableNode.m in Sources */,
509E68661B3AEDD7009B9150 /* CGRect+ASConvenience.m in Sources */, 509E68661B3AEDD7009B9150 /* CGRect+ASConvenience.m in Sources */,
254C6B8D1BF94F8A003EC431 /* ASEqualityHashHelpers.mm in Sources */, 254C6B8D1BF94F8A003EC431 /* ASEqualityHashHelpers.mm in Sources */,
254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.m in Sources */, 254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.m in Sources */,

View File

@ -10,6 +10,7 @@
#import "ASCollectionInternal.h" #import "ASCollectionInternal.h"
#import "ASCollectionViewLayoutFacilitatorProtocol.h" #import "ASCollectionViewLayoutFacilitatorProtocol.h"
#import "ASDisplayNode+Subclasses.h" #import "ASDisplayNode+Subclasses.h"
#import "ASEnvironmentInternal.h"
#import "ASRangeControllerUpdateRangeProtocol+Beta.h" #import "ASRangeControllerUpdateRangeProtocol+Beta.h"
#include <vector> #include <vector>
@ -53,6 +54,9 @@
#endif #endif
@interface ASCollectionNode () @interface ASCollectionNode ()
{
ASDN::RecursiveMutex _environmentStateLock;
}
@property (nonatomic) _ASCollectionPendingState *pendingState; @property (nonatomic) _ASCollectionPendingState *pendingState;
@end @end
@ -244,4 +248,6 @@
[self.view reloadDataImmediately]; [self.view reloadDataImmediately];
} }
ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock)
@end @end

View File

@ -342,7 +342,7 @@ NS_ASSUME_NONNULL_BEGIN
* This is a node-based UICollectionViewDataSource. * This is a node-based UICollectionViewDataSource.
*/ */
#define ASCollectionViewDataSource ASCollectionDataSource #define ASCollectionViewDataSource ASCollectionDataSource
@protocol ASCollectionDataSource <ASCommonCollectionViewDataSource, NSObject> @protocol ASCollectionDataSource <ASCommonCollectionViewDataSource>
@optional @optional

View File

@ -91,7 +91,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
#pragma mark - #pragma mark -
#pragma mark ASCollectionView. #pragma mark ASCollectionView.
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView> { @interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView, ASDataControllerEnvironmentDelegate> {
ASCollectionViewProxy *_proxyDataSource; ASCollectionViewProxy *_proxyDataSource;
ASCollectionViewProxy *_proxyDelegate; ASCollectionViewProxy *_proxyDelegate;
@ -225,6 +225,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
_dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:NO]; _dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:NO];
_dataController.delegate = _rangeController; _dataController.delegate = _rangeController;
_dataController.dataSource = self; _dataController.dataSource = self;
_dataController.environmentDelegate = self;
_batchContext = [[ASBatchContext alloc] init]; _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 // 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 // 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 // will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
// super.dataSource in this case because calls to ASCollectionViewProxy will start failing and cause crashes. // 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) { if (asyncDataSource == nil) {
_asyncDataSource = nil; _asyncDataSource = nil;
_proxyDataSource = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self]; _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 // 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 // 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 // will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
// super.delegate in this case because calls to ASCollectionViewProxy will start failing and cause crashes. // 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;
// Order is important here, the asyncDelegate must be callable while nilling super.delegate to avoid random crashes
// in UIScrollViewAccessibility.
super.delegate = nil;
if (asyncDelegate == nil) { if (asyncDelegate == nil) {
_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 #pragma mark - ASCollectionViewDataControllerSource Supplementary view support
- (ASCellNode *)dataController:(ASCollectionDataController *)dataController supplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath - (ASCellNode *)dataController:(ASCollectionDataController *)dataController supplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

View File

@ -22,6 +22,7 @@
#import "_ASCoreAnimationExtras.h" #import "_ASCoreAnimationExtras.h"
#import "ASDisplayNodeLayoutContext.h" #import "ASDisplayNodeLayoutContext.h"
#import "ASDisplayNodeExtras.h" #import "ASDisplayNodeExtras.h"
#import "ASTraitCollection.h"
#import "ASEqualityHelpers.h" #import "ASEqualityHelpers.h"
#import "ASRunLoopQueue.h" #import "ASRunLoopQueue.h"
#import "ASEnvironmentInternal.h" #import "ASEnvironmentInternal.h"
@ -2710,9 +2711,24 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority";
return ASEnvironmentStatePropagationEnabled(); return ASEnvironmentStatePropagationEnabled();
} }
- (BOOL)supportsTraitsCollectionPropagation
{
return ASEnvironmentStateTraitCollectionPropagationEnabled();
}
- (ASEnvironmentTraitCollection)environmentTraitCollection
{
return _environmentState.traitCollection;
}
ASEnvironmentLayoutOptionsForwarding ASEnvironmentLayoutOptionsForwarding
ASEnvironmentLayoutExtensibilityForwarding ASEnvironmentLayoutExtensibilityForwarding
- (ASTraitCollection *)asyncTraitCollection
{
ASDN::MutexLocker l(_propertyLock);
return [ASTraitCollection traitCollectionWithASEnvironmentTraitCollection:_environmentState.traitCollection];
}
#if TARGET_OS_TV #if TARGET_OS_TV
#pragma mark - UIFocusEnvironment Protocol (tvOS) #pragma mark - UIFocusEnvironment Protocol (tvOS)

View File

@ -117,13 +117,20 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) {
*/ */
@property (nullable, nonatomic, readonly) ASImageIdentifier displayedImageIdentifier; @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 #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. * @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. * @see `+[NSURL URLWithAssetLocalIdentifier:targetSize:contentMode:options:]` below.
*/ */
@property (nonatomic, strong) PHImageManager *imageManager; @property (nullable, nonatomic, strong) PHImageManager *imageManager;
#endif #endif
@end @end

View File

@ -85,6 +85,10 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
ASDN::RecursiveMutex _downloadIdentifierLock; ASDN::RecursiveMutex _downloadIdentifierLock;
id _downloadIdentifier; id _downloadIdentifier;
// Properties
ASDN::RecursiveMutex _propertyLock;
BOOL _shouldRenderProgressImages;
//set on init only //set on init only
BOOL _downloaderSupportsNewProtocol; BOOL _downloaderSupportsNewProtocol;
BOOL _downloaderImplementsSetProgress; BOOL _downloaderImplementsSetProgress;
@ -186,6 +190,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
_cacheSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)]; _cacheSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)];
_cacheSupportsClearing = [cache respondsToSelector:@selector(clearFetchedImageFromCacheWithURL:)]; _cacheSupportsClearing = [cache respondsToSelector:@selector(clearFetchedImageFromCacheWithURL:)];
_shouldRenderProgressImages = YES;
self.shouldBypassEnsureDisplay = YES; self.shouldBypassEnsureDisplay = YES;
return self; return self;
@ -339,6 +345,27 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
#endif #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 -
#pragma mark - #pragma mark -
@ -436,8 +463,12 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
} }
// Grab the best available image from the data source. // Grab the best available image from the data source.
UIImage *existingImage = self.image;
for (id imageIdentifier in _imageIdentifiers) { 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 (image) {
if (imageIdentifierOut) { if (imageIdentifierOut) {
*imageIdentifierOut = imageIdentifier; *imageIdentifierOut = imageIdentifier;
@ -458,6 +489,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
*/ */
- (void)_updateProgressImageBlockOnDownloaderIfNeeded - (void)_updateProgressImageBlockOnDownloaderIfNeeded
{ {
BOOL shouldRenderProgressImages = self.shouldRenderProgressImages;
// Read our interface state before locking so that we don't lock super while holding our lock. // Read our interface state before locking so that we don't lock super while holding our lock.
ASInterfaceState interfaceState = self.interfaceState; ASInterfaceState interfaceState = self.interfaceState;
ASDN::MutexLocker l(_downloadIdentifierLock); ASDN::MutexLocker l(_downloadIdentifierLock);
@ -467,7 +500,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
} }
ASImageDownloaderProgressImage progress = nil; ASImageDownloaderProgressImage progress = nil;
if (ASInterfaceStateIncludesVisible(interfaceState)) { if (shouldRenderProgressImages && ASInterfaceStateIncludesVisible(interfaceState)) {
__weak __typeof__(self) weakSelf = self; __weak __typeof__(self) weakSelf = self;
progress = ^(UIImage * _Nonnull progressImage, CGFloat progress, id _Nullable downloadIdentifier) { progress = ^(UIImage * _Nonnull progressImage, CGFloat progress, id _Nullable downloadIdentifier) {
__typeof__(self) strongSelf = weakSelf; __typeof__(self) strongSelf = weakSelf;

View 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

View 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

View File

@ -73,6 +73,13 @@ NS_ASSUME_NONNULL_BEGIN
*/ */
@property (nonatomic, assign, readwrite) BOOL shouldCacheImage; @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 * 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. * progressive progress. Calculated by dividing number of bytes / expected number of total bytes.

View File

@ -46,6 +46,8 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
BOOL _delegateSupportsDidFailWithError; BOOL _delegateSupportsDidFailWithError;
BOOL _delegateSupportsImageNodeDidFinishDecoding; BOOL _delegateSupportsImageNodeDidFinishDecoding;
BOOL _shouldRenderProgressImages;
//set on init only //set on init only
BOOL _downloaderSupportsNewProtocol; BOOL _downloaderSupportsNewProtocol;
BOOL _downloaderImplementsSetProgress; BOOL _downloaderImplementsSetProgress;
@ -83,6 +85,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
_cacheSupportsSynchronousFetch = [cache respondsToSelector:@selector(synchronouslyFetchedCachedImageWithURL:)]; _cacheSupportsSynchronousFetch = [cache respondsToSelector:@selector(synchronouslyFetchedCachedImageWithURL:)];
_shouldCacheImage = YES; _shouldCacheImage = YES;
_shouldRenderProgressImages = YES;
self.shouldBypassEnsureDisplay = YES; self.shouldBypassEnsureDisplay = YES;
return self; return self;
@ -218,6 +221,26 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
return _delegate; 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 - (BOOL)placeholderShouldPersist
{ {
ASDN::MutexLocker l(_lock); ASDN::MutexLocker l(_lock);
@ -309,6 +332,8 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
*/ */
- (void)_updateProgressImageBlockOnDownloaderIfNeeded - (void)_updateProgressImageBlockOnDownloaderIfNeeded
{ {
BOOL shouldRenderProgressImages = self.shouldRenderProgressImages;
// Read our interface state before locking so that we don't lock super while holding our lock. // Read our interface state before locking so that we don't lock super while holding our lock.
ASInterfaceState interfaceState = self.interfaceState; ASInterfaceState interfaceState = self.interfaceState;
ASDN::MutexLocker l(_lock); ASDN::MutexLocker l(_lock);
@ -318,7 +343,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
} }
ASImageDownloaderProgressImage progress = nil; ASImageDownloaderProgressImage progress = nil;
if (ASInterfaceStateIncludesVisible(interfaceState)) { if (shouldRenderProgressImages && ASInterfaceStateIncludesVisible(interfaceState)) {
__weak __typeof__(self) weakSelf = self; __weak __typeof__(self) weakSelf = self;
progress = ^(UIImage * _Nonnull progressImage, CGFloat progress, id _Nullable downloadIdentifier) { progress = ^(UIImage * _Nonnull progressImage, CGFloat progress, id _Nullable downloadIdentifier) {
__typeof__(self) strongSelf = weakSelf; __typeof__(self) strongSelf = weakSelf;

View File

@ -11,7 +11,8 @@
@class ASPagerNode; @class ASPagerNode;
@class ASPagerFlowLayout; @class ASPagerFlowLayout;
@protocol ASPagerNodeDataSource <NSObject> #define ASPagerNodeDataSource ASPagerDataSource
@protocol ASPagerDataSource <NSObject>
/** /**
* This method replaces -collectionView:numberOfItemsInSection: * This method replaces -collectionView:numberOfItemsInSection:
@ -65,25 +66,30 @@
@end @end
@protocol ASPagerDelegate <ASCollectionDelegate>
@end
@interface ASPagerNode : ASCollectionNode @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; - (instancetype)init;
// Initializer with custom-configured flow layout properties. /// Initializer with custom-configured flow layout properties.
- (instancetype)initWithCollectionViewLayout:(ASPagerFlowLayout *)flowLayout; - (instancetype)initWithCollectionViewLayout:(ASPagerFlowLayout *)flowLayout;
// Data Source is required, and uses a different protocol from ASCollectionNode. /// Data Source is required, and uses a different protocol from ASCollectionNode.
- (void)setDataSource:(id <ASPagerNodeDataSource>)dataSource; - (void)setDataSource:(id <ASPagerDataSource>)dataSource;
- (id <ASPagerNodeDataSource>)dataSource; - (id <ASPagerDataSource>)dataSource;
// Delegate is optional, and uses the same protocol as ASCollectionNode. // Delegate is optional, and uses the same protocol as ASCollectionNode.
// This includes UIScrollViewDelegate as well as most methods from UICollectionViewDelegate, like willDisplay... // 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; @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; - (void)scrollToPageAtIndex:(NSInteger)index animated:(BOOL)animated;
@end @end

View File

@ -16,7 +16,7 @@
{ {
ASPagerFlowLayout *_flowLayout; ASPagerFlowLayout *_flowLayout;
ASPagerNodeProxy *_proxy; ASPagerNodeProxy *_proxy;
__weak id <ASPagerNodeDataSource> _pagerDataSource; __weak id <ASPagerDataSource> _pagerDataSource;
BOOL _pagerDataSourceImplementsNodeBlockAtIndex; BOOL _pagerDataSourceImplementsNodeBlockAtIndex;
BOOL _pagerDataSourceImplementsConstrainedSizeForNode; BOOL _pagerDataSourceImplementsConstrainedSizeForNode;
} }
@ -111,12 +111,12 @@
#pragma mark - Data Source Proxy #pragma mark - Data Source Proxy
- (id <ASPagerNodeDataSource>)dataSource - (id <ASPagerDataSource>)dataSource
{ {
return _pagerDataSource; return _pagerDataSource;
} }
- (void)setDataSource:(id <ASPagerNodeDataSource>)pagerDataSource - (void)setDataSource:(id <ASPagerDataSource>)pagerDataSource
{ {
if (pagerDataSource != _pagerDataSource) { if (pagerDataSource != _pagerDataSource) {
_pagerDataSource = pagerDataSource; _pagerDataSource = pagerDataSource;

View 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

View 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

View File

@ -6,6 +6,7 @@
// Copyright © 2015 Facebook. All rights reserved. // Copyright © 2015 Facebook. All rights reserved.
// //
#import "ASEnvironmentInternal.h"
#import "ASFlowLayoutController.h" #import "ASFlowLayoutController.h"
#import "ASTableViewInternal.h" #import "ASTableViewInternal.h"
#import "ASDisplayNode+Subclasses.h" #import "ASDisplayNode+Subclasses.h"
@ -20,6 +21,10 @@
@end @end
@interface ASTableNode () @interface ASTableNode ()
{
ASDN::RecursiveMutex _environmentStateLock;
}
@property (nonatomic, strong) _ASTablePendingState *pendingState; @property (nonatomic, strong) _ASTablePendingState *pendingState;
@end @end
@ -158,4 +163,6 @@
[self.view clearFetchedData]; [self.view clearFetchedData];
} }
ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock)
@end @end

View File

@ -16,6 +16,7 @@
#import "ASDisplayNodeExtras.h" #import "ASDisplayNodeExtras.h"
#import "ASDisplayNode+Beta.h" #import "ASDisplayNode+Beta.h"
#import "ASDisplayNode+FrameworkPrivate.h" #import "ASDisplayNode+FrameworkPrivate.h"
#import "ASEnvironmentInternal.h"
#import "ASInternalHelpers.h" #import "ASInternalHelpers.h"
#import "ASLayout.h" #import "ASLayout.h"
#import "ASLayoutController.h" #import "ASLayoutController.h"
@ -88,7 +89,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
- (instancetype)_initWithTableView:(ASTableView *)tableView; - (instancetype)_initWithTableView:(ASTableView *)tableView;
@end @end
@interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView> @interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView, ASDataControllerEnvironmentDelegate>
{ {
ASTableViewProxy *_proxyDataSource; ASTableViewProxy *_proxyDataSource;
ASTableViewProxy *_proxyDelegate; ASTableViewProxy *_proxyDelegate;
@ -175,6 +176,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
_dataController = [[dataControllerClass alloc] initWithAsyncDataFetching:NO]; _dataController = [[dataControllerClass alloc] initWithAsyncDataFetching:NO];
_dataController.dataSource = self; _dataController.dataSource = self;
_dataController.delegate = _rangeController; _dataController.delegate = _rangeController;
_dataController.environmentDelegate = self;
_layoutController.dataSource = _dataController; _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 // 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 // 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 // will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
// super.dataSource in this case because calls to ASTableViewProxy will start failing and cause crashes. // 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;
super.dataSource = nil;
if (asyncDataSource == nil) { if (asyncDataSource == nil) {
_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 // 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 // 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 // will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
// super.delegate in this case because calls to ASTableViewProxy will start failing and cause crashes. // 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;
// Order is important here, the asyncDelegate must be callable while nilling super.delegate to avoid random crashes
// in UIScrollViewAccessibility.
super.delegate = nil;
if (asyncDelegate == nil) { if (asyncDelegate == nil) {
_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 #pragma mark - _ASTableViewCellDelegate
- (void)didLayoutSubviewsOfTableViewCell:(_ASTableViewCell *)tableViewCell - (void)didLayoutSubviewsOfTableViewCell:(_ASTableViewCell *)tableViewCell

View File

@ -34,19 +34,19 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
@interface ASTextNode : ASControlNode @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. @discussion Defaults to nil, no text is shown.
For inline image attachments, add an attribute of key NSAttachmentAttributeName, with a value of an NSTextAttachment. 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 #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. @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. @summary The second attributed string appended for truncation.
@ -270,4 +270,28 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
@end @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 NS_ASSUME_NONNULL_END

View File

@ -67,7 +67,7 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
NSArray *_exclusionPaths; NSArray *_exclusionPaths;
NSAttributedString *_composedTruncationString; NSAttributedString *_composedTruncationText;
NSString *_highlightedLinkAttributeName; NSString *_highlightedLinkAttributeName;
id _highlightedLinkAttributeValue; id _highlightedLinkAttributeValue;
@ -105,7 +105,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
self.needsDisplayOnBoundsChange = YES; self.needsDisplayOnBoundsChange = YES;
_truncationMode = NSLineBreakByWordWrapping; _truncationMode = NSLineBreakByWordWrapping;
_composedTruncationString = DefaultTruncationAttributedString(); _composedTruncationText = DefaultTruncationAttributedString();
// The common case is for a text node to be non-opaque and blended over some background. // The common case is for a text node to be non-opaque and blended over some background.
self.opaque = NO; self.opaque = NO;
@ -158,8 +158,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
- (NSString *)description - (NSString *)description
{ {
NSString *plainString = [[_attributedString string] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]; NSString *plainString = [[_attributedText string] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSString *truncationString = [_composedTruncationString string]; NSString *truncationString = [_composedTruncationText string];
if (plainString.length > 50) if (plainString.length > 50)
plainString = [[plainString substringToIndex:50] stringByAppendingString:@"\u2026"]; 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]; 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 - (ASTextKitAttributes)_rendererAttributes
{ {
return { return {
.attributedString = _attributedString, .attributedString = _attributedText,
.truncationAttributedString = _composedTruncationString, .truncationAttributedString = _composedTruncationText,
.lineBreakMode = _truncationMode, .lineBreakMode = _truncationMode,
.maximumNumberOfLines = _maximumNumberOfLines, .maximumNumberOfLines = _maximumNumberOfLines,
.exclusionPaths = _exclusionPaths, .exclusionPaths = _exclusionPaths,
@ -340,10 +340,10 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
[self setNeedsDisplay]; [self setNeedsDisplay];
CGSize size = [[self _renderer] size]; CGSize size = [[self _renderer] size];
if (self.attributedString.length > 0) { if (_attributedText.length > 0) {
CGFloat screenScale = ASScreenScale(); CGFloat screenScale = ASScreenScale();
self.ascender = round([[_attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale; self.ascender = round([[_attributedText 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.descender = round([[_attributedText attribute:NSFontAttributeName atIndex:_attributedText.length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale;
if (_renderer.currentScaleFactor > 0 && _renderer.currentScaleFactor < 1.0) { 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. // while not perfect, this is a good estimate of what the ascender of the scaled font will be.
self.ascender *= _renderer.currentScaleFactor; self.ascender *= _renderer.currentScaleFactor;
@ -355,28 +355,28 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
#pragma mark - Modifying User Text #pragma mark - Modifying User Text
- (void)setAttributedString:(NSAttributedString *)attributedString - (void)setAttributedText:(NSAttributedString *)attributedText
{ {
if (attributedString == nil) { if (attributedText == nil) {
attributedString = [[NSAttributedString alloc] initWithString:@"" attributes:nil]; attributedText = [[NSAttributedString alloc] initWithString:@"" attributes:nil];
} }
if (ASObjectIsEqual(attributedString, _attributedString)) { if (ASObjectIsEqual(attributedText, _attributedText)) {
return; return;
} }
_attributedString = ASCleanseAttributedStringOfCoreTextAttributes(attributedString); _attributedText = ASCleanseAttributedStringOfCoreTextAttributes(attributedText);
if (_attributedString.length > 0) { if (_attributedText.length > 0) {
CGFloat screenScale = ASScreenScale(); CGFloat screenScale = ASScreenScale();
self.ascender = round([[_attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale; self.ascender = round([[_attributedText 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.descender = round([[_attributedText attribute:NSFontAttributeName atIndex:_attributedText.length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale;
} }
// Sync the truncation string with attributes from the updated _attributedString // Sync the truncation string with attributes from the updated _attributedString
// Without this, the size calculation of the text with truncation applied will // Without this, the size calculation of the text with truncation applied will
// not take into account the attributes of attributedString in the last line // not take into account the attributes of attributedText in the last line
[self _updateComposedTruncationString]; [self _updateComposedTruncationText];
// We need an entirely new renderer // We need an entirely new renderer
[self _invalidateRenderer]; [self _invalidateRenderer];
@ -386,10 +386,10 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
[self setNeedsDisplay]; [self setNeedsDisplay];
self.accessibilityLabel = _attributedString.string; self.accessibilityLabel = _attributedText.string;
// We're an accessibility element by default if there is a 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 #pragma mark - Text Layout
@ -470,7 +470,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
{ {
ASTextKitRenderer *renderer = [self _renderer]; ASTextKitRenderer *renderer = [self _renderer];
NSRange visibleRange = renderer.visibleRanges[0]; NSRange visibleRange = renderer.visibleRanges[0];
NSAttributedString *attributedString = _attributedString; NSAttributedString *attributedString = _attributedText;
NSRange clampedRange = NSIntersectionRange(visibleRange, NSMakeRange(0, attributedString.length)); NSRange clampedRange = NSIntersectionRange(visibleRange, NSMakeRange(0, attributedString.length));
// Check in a 9-point region around the actual touch point so we make sure // Check in a 9-point region around the actual touch point so we make sure
@ -1023,14 +1023,14 @@ static NSAttributedString *DefaultTruncationAttributedString()
return defaultTruncationAttributedString; return defaultTruncationAttributedString;
} }
- (void)setTruncationAttributedString:(NSAttributedString *)truncationAttributedString - (void)setTruncationAttributedText:(NSAttributedString *)truncationAttributedText
{ {
if (ASObjectIsEqual(_truncationAttributedString, truncationAttributedString)) { if (ASObjectIsEqual(_truncationAttributedText, truncationAttributedText)) {
return; return;
} }
_truncationAttributedString = [truncationAttributedString copy]; _truncationAttributedText = [truncationAttributedText copy];
[self _invalidateTruncationString]; [self _invalidateTruncationText];
} }
- (void)setAdditionalTruncationMessage:(NSAttributedString *)additionalTruncationMessage - (void)setAdditionalTruncationMessage:(NSAttributedString *)additionalTruncationMessage
@ -1040,7 +1040,7 @@ static NSAttributedString *DefaultTruncationAttributedString()
} }
_additionalTruncationMessage = [additionalTruncationMessage copy]; _additionalTruncationMessage = [additionalTruncationMessage copy];
[self _invalidateTruncationString]; [self _invalidateTruncationText];
} }
- (void)setTruncationMode:(NSLineBreakMode)truncationMode - (void)setTruncationMode:(NSLineBreakMode)truncationMode
@ -1055,7 +1055,7 @@ static NSAttributedString *DefaultTruncationAttributedString()
- (BOOL)isTruncated - (BOOL)isTruncated
{ {
NSRange visibleRange = [self _renderer].visibleRanges[0]; NSRange visibleRange = [self _renderer].visibleRanges[0];
return visibleRange.length < _attributedString.length; return visibleRange.length < _attributedText.length;
} }
- (void)setPointSizeScaleFactors:(NSArray *)pointSizeScaleFactors - (void)setPointSizeScaleFactors:(NSArray *)pointSizeScaleFactors
@ -1082,14 +1082,14 @@ static NSAttributedString *DefaultTruncationAttributedString()
#pragma mark - Truncation Message #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 _invalidateRenderer];
[self setNeedsDisplay]; [self setNeedsDisplay];
} }
@ -1111,7 +1111,7 @@ static NSAttributedString *DefaultTruncationAttributedString()
NSUInteger additionalTruncationMessageLength = _additionalTruncationMessage.length; NSUInteger additionalTruncationMessageLength = _additionalTruncationMessage.length;
// We get the location of the truncation token, then add the length of the // We get the location of the truncation token, then add the length of the
// truncation attributed string +1 for the space between. // 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; return range;
} }
@ -1120,24 +1120,24 @@ static NSAttributedString *DefaultTruncationAttributedString()
* additional truncation message and a truncation attributed string, they will * additional truncation message and a truncation attributed string, they will
* be properly composed. * be properly composed.
*/ */
- (NSAttributedString *)_composedTruncationString - (NSAttributedString *)_composedTruncationText
{ {
//If we have neither return the default //If we have neither return the default
if (!_additionalTruncationMessage && !_truncationAttributedString) { if (!_additionalTruncationMessage && !_truncationAttributedText) {
return _composedTruncationString; return _composedTruncationText;
} }
// Short circuit if we only have one or the other. // Short circuit if we only have one or the other.
if (!_additionalTruncationMessage) { if (!_additionalTruncationMessage) {
return _truncationAttributedString; return _truncationAttributedText;
} }
if (!_truncationAttributedString) { if (!_truncationAttributedText) {
return _additionalTruncationMessage; return _additionalTruncationMessage;
} }
// If we've reached this point, both _additionalTruncationMessage and // If we've reached this point, both _additionalTruncationMessage and
// _truncationAttributedString are present. Compose them. // _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 replaceCharactersInRange:NSMakeRange(newComposedTruncationString.length, 0) withString:@" "];
[newComposedTruncationString appendAttributedString:_additionalTruncationMessage]; [newComposedTruncationString appendAttributedString:_additionalTruncationMessage];
return newComposedTruncationString; return newComposedTruncationString;
@ -1153,9 +1153,9 @@ static NSAttributedString *DefaultTruncationAttributedString()
truncationString = ASCleanseAttributedStringOfCoreTextAttributes(truncationString); truncationString = ASCleanseAttributedStringOfCoreTextAttributes(truncationString);
NSMutableAttributedString *truncationMutableString = [truncationString mutableCopy]; NSMutableAttributedString *truncationMutableString = [truncationString mutableCopy];
// Grab the attributes from the full string // Grab the attributes from the full string
if (_attributedString.length > 0) { if (_attributedText.length > 0) {
NSAttributedString *originalString = _attributedString; NSAttributedString *originalString = _truncationAttributedText;
NSInteger originalStringLength = _attributedString.length; NSInteger originalStringLength = _truncationAttributedText.length;
// Add any of the original string's attributes to the truncation string, // Add any of the original string's attributes to the truncation string,
// but don't overwrite any of the truncation string's attributes // but don't overwrite any of the truncation string's attributes
NSDictionary *originalStringAttributes = [originalString attributesAtIndex:originalStringLength-1 effectiveRange:NULL]; NSDictionary *originalStringAttributes = [originalString attributesAtIndex:originalStringLength-1 effectiveRange:NULL];
@ -1170,3 +1170,27 @@ static NSAttributedString *DefaultTruncationAttributedString()
} }
@end @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

View File

@ -64,9 +64,9 @@ static NSString * const kStatus = @"status";
ASImageNode *_placeholderImageNode; // TODO: Make ASVideoNode an ASImageNode subclass; remove this. ASImageNode *_placeholderImageNode; // TODO: Make ASVideoNode an ASImageNode subclass; remove this.
ASButtonNode *_playButton; ASButtonNode *_playButtonNode;
ASDisplayNode *_playerNode; ASDisplayNode *_playerNode;
ASDisplayNode *_spinner; ASDisplayNode *_spinnerNode;
NSString *_gravity; NSString *_gravity;
} }
@ -185,6 +185,45 @@ static NSString * const kStatus = @"status";
[notificationCenter removeObserver:self name:AVPlayerItemNewErrorLogEntryNotification object:playerItem]; [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 - (void)layout
{ {
[super layout]; [super layout];
@ -192,17 +231,9 @@ static NSString * const kStatus = @"status";
CGRect bounds = self.bounds; CGRect bounds = self.bounds;
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
CGFloat horizontalDiff = (CGRectGetWidth(bounds) - CGRectGetWidth(_playButtonNode.bounds))/2;
_placeholderImageNode.frame = bounds; CGFloat verticalDiff = (CGRectGetHeight(bounds) - CGRectGetHeight(_playButtonNode.bounds))/2;
_playerNode.frame = bounds; _playButtonNode.hitTestSlop = UIEdgeInsetsMake(-verticalDiff, -horizontalDiff, -verticalDiff, -horizontalDiff);
_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);
} }
- (void)generatePlaceholderImage - (void)generatePlaceholderImage
@ -370,6 +401,7 @@ static NSString * const kStatus = @"status";
#pragma mark - Video Properties #pragma mark - Video Properties
- (void)setPlayerState:(ASVideoNodePlayerState)playerState - (void)setPlayerState:(ASVideoNodePlayerState)playerState
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
@ -385,28 +417,26 @@ static NSString * const kStatus = @"status";
} }
_playerState = playerState; _playerState = playerState;
} }
- (void)setPlayButton:(ASButtonNode *)playButton - (void)setPlayButton:(ASButtonNode *)playButton
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
[_playButton removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside]; [_playButtonNode removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
[_playButton removeFromSupernode]; [_playButtonNode removeFromSupernode];
_playButton = playButton; _playButtonNode = playButton;
[_playButtonNode addTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
[self addSubnode:playButton]; [self addSubnode:playButton];
[self setNeedsLayout];
[_playButton addTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
} }
- (ASButtonNode *)playButton - (ASButtonNode *)playButton
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
return _playButtonNode;
return _playButton;
} }
- (void)setAsset:(AVAsset *)asset - (void)setAsset:(AVAsset *)asset
@ -471,14 +501,12 @@ static NSString * const kStatus = @"status";
- (NSString *)gravity - (NSString *)gravity
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
return _gravity; return _gravity;
} }
- (BOOL)muted - (BOOL)muted
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
return _muted; return _muted;
} }
@ -507,11 +535,13 @@ static NSString * const kStatus = @"status";
if (_playerNode == nil) { if (_playerNode == nil) {
_playerNode = [self constructPlayerNode]; _playerNode = [self constructPlayerNode];
if (_playButton.supernode == self) { if (_playButtonNode.supernode == self) {
[self insertSubnode:_playerNode belowSubnode:_playButton]; [self insertSubnode:_playerNode belowSubnode:_playButtonNode];
} else { } else {
[self addSubnode:_playerNode]; [self addSubnode:_playerNode];
} }
[self setNeedsLayout];
} }
@ -519,7 +549,7 @@ static NSString * const kStatus = @"status";
_shouldBePlaying = YES; _shouldBePlaying = YES;
[UIView animateWithDuration:0.15 animations:^{ [UIView animateWithDuration:0.15 animations:^{
_playButton.alpha = 0.0; _playButtonNode.alpha = 0.0;
}]; }];
if (![self ready]) { if (![self ready]) {
[self showSpinner]; [self showSpinner];
@ -538,28 +568,29 @@ static NSString * const kStatus = @"status";
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
if (!_spinner) { if (!_spinnerNode) {
_spinner = [[ASDisplayNode alloc] initWithViewBlock:^UIView *{ _spinnerNode = [[ASDisplayNode alloc] initWithViewBlock:^UIView *{
UIActivityIndicatorView *spinnnerView = [[UIActivityIndicatorView alloc] init]; UIActivityIndicatorView *spinnnerView = [[UIActivityIndicatorView alloc] init];
spinnnerView.color = [UIColor whiteColor]; spinnnerView.color = [UIColor whiteColor];
return spinnnerView; 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 - (void)removeSpinner
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
if (!_spinner) { if (!_spinnerNode) {
return; return;
} }
[_spinner removeFromSupernode]; [_spinnerNode removeFromSupernode];
_spinner = nil; _spinnerNode = nil;
} }
- (void)pause - (void)pause
@ -573,7 +604,7 @@ static NSString * const kStatus = @"status";
[self removeSpinner]; [self removeSpinner];
_shouldBePlaying = NO; _shouldBePlaying = NO;
[UIView animateWithDuration:0.15 animations:^{ [UIView animateWithDuration:0.15 animations:^{
_playButton.alpha = 1.0; _playButtonNode.alpha = 1.0;
}]; }];
} }
@ -634,7 +665,7 @@ static NSString * const kStatus = @"status";
- (ASDisplayNode *)spinner - (ASDisplayNode *)spinner
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
return _spinner; return _spinnerNode;
} }
- (ASImageNode *)placeholderImageNode - (ASImageNode *)placeholderImageNode
@ -670,6 +701,8 @@ static NSString * const kStatus = @"status";
{ {
ASDN::MutexLocker l(_videoLock); ASDN::MutexLocker l(_videoLock);
_playerNode = playerNode; _playerNode = playerNode;
[self setNeedsLayout];
} }
- (void)setPlayer:(AVPlayer *)player - (void)setPlayer:(AVPlayer *)player
@ -698,7 +731,7 @@ static NSString * const kStatus = @"status";
{ {
[_player removeTimeObserver:_timeObserver]; [_player removeTimeObserver:_timeObserver];
_timeObserver = nil; _timeObserver = nil;
[_playButton removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside]; [_playButtonNode removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
[self removePlayerItemObservers:_currentPlayerItem]; [self removePlayerItemObservers:_currentPlayerItem];
} }

View File

@ -8,15 +8,43 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <AsyncDisplayKit/ASDisplayNode.h> #import <AsyncDisplayKit/ASDisplayNode.h>
#import <AsyncDisplayKit/ASVisibilityProtocols.h>
@class ASTraitCollection;
NS_ASSUME_NONNULL_BEGIN 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; - (instancetype)initWithNode:(DisplayNodeType)node NS_DESIGNATED_INITIALIZER;
@property (nonatomic, strong, readonly) DisplayNodeType node; @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. * @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. * @return The current ASInterfaceState of the node, indicating whether it is visible and other situational properties.

View File

@ -13,10 +13,14 @@
#import "ASDisplayNode+Beta.h" #import "ASDisplayNode+Beta.h"
#import "ASRangeControllerUpdateRangeProtocol+Beta.h" #import "ASRangeControllerUpdateRangeProtocol+Beta.h"
#define AS_LOG_VISIBILITY_CHANGES 0
@implementation ASViewController @implementation ASViewController
{ {
BOOL _ensureDisplayed; BOOL _ensureDisplayed;
BOOL _automaticallyAdjustRangeModeBasedOnViewEvents; BOOL _automaticallyAdjustRangeModeBasedOnViewEvents;
BOOL _parentManagesVisibilityDepth;
NSInteger _visibilityDepth;
} }
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
@ -81,6 +85,8 @@
[super viewDidLayoutSubviews]; [super viewDidLayoutSubviews];
} }
ASVisibilityDidMoveToParentViewController;
- (void)viewWillAppear:(BOOL)animated - (void)viewWillAppear:(BOOL)animated
{ {
[super viewWillAppear:animated]; [super viewWillAppear:animated];
@ -88,14 +94,45 @@
[_node measureWithSizeRange:[self nodeConstrainedSize]]; [_node measureWithSizeRange:[self nodeConstrainedSize]];
[_node recursivelyFetchData]; [_node recursivelyFetchData];
[self updateCurrentRangeModeWithModeIfPossible:ASLayoutRangeModeFull]; if (_parentManagesVisibilityDepth == NO) {
[self setVisibilityDepth:0];
}
} }
- (void)viewDidDisappear:(BOOL)animated ASVisibilitySetVisibilityDepth;
{
[super viewDidDisappear:animated];
[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 #pragma mark - Automatic range mode
@ -113,7 +150,9 @@
- (void)updateCurrentRangeModeWithModeIfPossible:(ASLayoutRangeMode)rangeMode - (void)updateCurrentRangeModeWithModeIfPossible:(ASLayoutRangeMode)rangeMode
{ {
if (!_automaticallyAdjustRangeModeBasedOnViewEvents) { return; } if (!_automaticallyAdjustRangeModeBasedOnViewEvents) { return; }
if (![_node conformsToProtocol:@protocol(ASRangeControllerUpdateRangeProtocol)]) { return; } if (![_node conformsToProtocol:@protocol(ASRangeControllerUpdateRangeProtocol)]) {
return;
}
id<ASRangeControllerUpdateRangeProtocol> updateRangeNode = (id<ASRangeControllerUpdateRangeProtocol>)_node; id<ASRangeControllerUpdateRangeProtocol> updateRangeNode = (id<ASRangeControllerUpdateRangeProtocol>)_node;
[updateRangeNode updateCurrentRangeWithMode:rangeMode]; [updateRangeNode updateCurrentRangeWithMode:rangeMode];

View 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]; \
}

View 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;
}

View File

@ -34,6 +34,8 @@
#import <AsyncDisplayKit/ASPagerNode.h> #import <AsyncDisplayKit/ASPagerNode.h>
#import <AsyncDisplayKit/ASViewController.h> #import <AsyncDisplayKit/ASViewController.h>
#import <AsyncDisplayKit/ASNavigationController.h>
#import <AsyncDisplayKit/ASTabBarController.h>
#import <AsyncDisplayKit/ASRangeControllerUpdateRangeProtocol+Beta.h> #import <AsyncDisplayKit/ASRangeControllerUpdateRangeProtocol+Beta.h>
#import <AsyncDisplayKit/ASChangeSetDataController.h> #import <AsyncDisplayKit/ASChangeSetDataController.h>
@ -77,6 +79,8 @@
#import <AsyncDisplayKit/UIView+ASConvenience.h> #import <AsyncDisplayKit/UIView+ASConvenience.h>
#import <AsyncDisplayKit/ASRunLoopQueue.h> #import <AsyncDisplayKit/ASRunLoopQueue.h>
#import <AsyncDisplayKit/ASTextKitComponents.h> #import <AsyncDisplayKit/ASTextKitComponents.h>
#import <AsyncDisplayKit/ASTraitCollection.h>
#import <AsyncDisplayKit/ASVisibilityProtocols.h>
#import <AsyncDisplayKit/AsyncDisplayKit+Debug.h> #import <AsyncDisplayKit/AsyncDisplayKit+Debug.h>

View File

@ -51,7 +51,9 @@
- (void)willReloadData - (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 // Remove everything that existed before the reload, now that we're ready to insert replacements
NSArray *indexPaths = [self indexPathsForEditingNodesOfKind:kind]; NSArray *indexPaths = [self indexPathsForEditingNodesOfKind:kind];
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil]; [self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
@ -72,7 +74,7 @@
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil]; [self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
}]; }];
[_pendingContexts removeObjectForKey:kind]; [_pendingContexts removeObjectForKey:kind];
}]; }
} }
- (void)prepareForInsertSections:(NSIndexSet *)sections - (void)prepareForInsertSections:(NSIndexSet *)sections
@ -87,7 +89,9 @@
- (void)willInsertSections:(NSIndexSet *)sections - (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]; NSMutableArray *sectionArray = [NSMutableArray arrayWithCapacity:sections.count];
for (NSUInteger i = 0; i < sections.count; i++) { for (NSUInteger i = 0; i < sections.count; i++) {
[sectionArray addObject:[NSMutableArray array]]; [sectionArray addObject:[NSMutableArray array]];
@ -98,7 +102,7 @@
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil]; [self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
}]; }];
[_pendingContexts removeObjectForKey:kind]; [_pendingContexts removeObjectForKey:kind];
}]; }
} }
- (void)willDeleteSections:(NSIndexSet *)sections - (void)willDeleteSections:(NSIndexSet *)sections
@ -122,7 +126,9 @@
- (void)willReloadSections:(NSIndexSet *)sections - (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); NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet([self editingNodesOfKind:kind], sections);
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil]; [self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
// reinsert the elements // reinsert the elements
@ -130,7 +136,7 @@
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil]; [self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
}]; }];
[_pendingContexts removeObjectForKey:kind]; [_pendingContexts removeObjectForKey:kind];
}]; }
} }
- (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection - (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection

View File

@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
@class ASCellNode; @class ASCellNode;
@class ASDataController; @class ASDataController;
@protocol ASEnvironment;
typedef NSUInteger ASDataControllerAnimationOptions; typedef NSUInteger ASDataControllerAnimationOptions;
@ -64,6 +65,11 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind;
*/ */
- (void)dataControllerUnlockDataSource; - (void)dataControllerUnlockDataSource;
@end
@protocol ASDataControllerEnvironmentDelegate
- (id<ASEnvironment>)dataControllerEnvironment;
@end @end
/** /**
@ -122,6 +128,11 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind;
*/ */
@property (nonatomic, weak) id<ASDataControllerDelegate> delegate; @property (nonatomic, weak) id<ASDataControllerDelegate> delegate;
/**
*
*/
@property (nonatomic, weak) id<ASDataControllerEnvironmentDelegate> environmentDelegate;
/** /**
* Designated initializer. * Designated initializer.
* *

View File

@ -13,6 +13,7 @@
#import "ASAssert.h" #import "ASAssert.h"
#import "ASCellNode.h" #import "ASCellNode.h"
#import "ASDisplayNode.h" #import "ASDisplayNode.h"
#import "ASEnvironmentInternal.h"
#import "ASFlowLayoutController.h" #import "ASFlowLayoutController.h"
#import "ASInternalHelpers.h" #import "ASInternalHelpers.h"
#import "ASLayout.h" #import "ASLayout.h"
@ -190,26 +191,32 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
for (NSUInteger j = 0; j < nodeCount; j += kASDataControllerSizingCountPerProcessor) { for (NSUInteger j = 0; j < nodeCount; j += kASDataControllerSizingCountPerProcessor) {
NSInteger batchCount = MIN(kASDataControllerSizingCountPerProcessor, nodeCount - j); NSInteger batchCount = MIN(kASDataControllerSizingCountPerProcessor, nodeCount - j);
__block NSArray *subarray;
// Allocate nodes concurrently. // Allocate nodes concurrently.
__block NSArray *subarrayOfContexts;
__block NSArray *subarrayOfNodes;
dispatch_block_t allocationBlock = ^{ dispatch_block_t allocationBlock = ^{
__strong ASIndexedNodeContext **allocatedContextBuffer = (__strong ASIndexedNodeContext **)calloc(batchCount, sizeof(ASIndexedNodeContext *));
__strong ASCellNode **allocatedNodeBuffer = (__strong ASCellNode **)calloc(batchCount, sizeof(ASCellNode *)); __strong ASCellNode **allocatedNodeBuffer = (__strong ASCellNode **)calloc(batchCount, sizeof(ASCellNode *));
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(batchCount, queue, ^(size_t i) { dispatch_apply(batchCount, queue, ^(size_t i) {
unsigned long k = j + i; unsigned long k = j + i;
ASCellNode *node = [contexts[k] allocateNode]; ASIndexedNodeContext *context = contexts[k];
ASCellNode *node = [context allocateNode];
if (node == nil) { if (node == nil) {
ASDisplayNodeAssertNotNil(node, @"Node block created nil node; %@, %@", self, self.dataSource); ASDisplayNodeAssertNotNil(node, @"Node block created nil node; %@, %@", self, self.dataSource);
node = [[ASCellNode alloc] init]; // Fallback to avoid crash for production apps. node = [[ASCellNode alloc] init]; // Fallback to avoid crash for production apps.
} }
allocatedNodeBuffer[i] = node; 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. // Nil out buffer indexes to allow arc to free the stored cells.
for (int i = 0; i < batchCount; i++) { for (int i = 0; i < batchCount; i++) {
allocatedContextBuffer[i] = nil;
allocatedNodeBuffer[i] = nil; allocatedNodeBuffer[i] = nil;
} }
free(allocatedContextBuffer);
free(allocatedNodeBuffer); free(allocatedNodeBuffer);
}; };
@ -224,15 +231,15 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
}); });
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 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 { } else {
allocationBlock(); allocationBlock();
[_mainSerialQueue performBlockOnMainThread:^{ [_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), ^{ 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. // 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++) { for (NSUInteger i = 0; i < rowNum; i++) {
NSIndexPath *indexPath = [sectionIndex indexPathByAddingIndex:i]; NSIndexPath *indexPath = [sectionIndex indexPathByAddingIndex:i];
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath]; 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]; ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:ASDataControllerRowNodeKind atIndexPath:indexPath];
[contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlock [contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlockPropagatingDisplayTraits
indexPath:indexPath indexPath:indexPath
constrainedSize:constrainedSize]]; constrainedSize:constrainedSize]];
} }

View File

@ -77,7 +77,7 @@
- (BOOL)interceptsSelector:(SEL)selector - (BOOL)interceptsSelector:(SEL)selector
{ {
return ( return (
// handled by ASPagerNodeDataSource node<->cell machinery // handled by ASPagerDataSource node<->cell machinery
selector == @selector(collectionView:nodeForItemAtIndexPath:) || selector == @selector(collectionView:nodeForItemAtIndexPath:) ||
selector == @selector(collectionView:nodeBlockForItemAtIndexPath:) || selector == @selector(collectionView:nodeBlockForItemAtIndexPath:) ||
selector == @selector(collectionView:numberOfItemsInSection:) || selector == @selector(collectionView:numberOfItemsInSection:) ||
@ -125,7 +125,15 @@
if (_target) { if (_target) {
return [_target respondsToSelector:aSelector] ? _target : nil; return [_target respondsToSelector:aSelector] ? _target : nil;
} else { } 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; return nil;
} }
} }

View File

@ -14,6 +14,8 @@
#import "ASStackLayoutDefines.h" #import "ASStackLayoutDefines.h"
#import "ASRelativeSize.h" #import "ASRelativeSize.h"
@protocol ASEnvironment;
@class UITraitCollection;
ASDISPLAYNODE_EXTERN_C_BEGIN ASDISPLAYNODE_EXTERN_C_BEGIN
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@ -59,17 +61,49 @@ typedef struct ASEnvironmentHierarchyState {
unsigned layoutPending:1; // = NO unsigned layoutPending:1; // = NO
} ASEnvironmentHierarchyState; } 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 #pragma mark - ASEnvironmentState
typedef struct ASEnvironmentState { typedef struct ASEnvironmentState {
struct ASEnvironmentHierarchyState hierarchyState; struct ASEnvironmentHierarchyState hierarchyState;
struct ASEnvironmentLayoutOptionsState layoutOptionsState; struct ASEnvironmentLayoutOptionsState layoutOptionsState;
struct ASEnvironmentTraitCollection traitCollection;
} ASEnvironmentState; } ASEnvironmentState;
extern ASEnvironmentState ASEnvironmentStateMakeDefault(); extern ASEnvironmentState ASEnvironmentStateMakeDefault();
ASDISPLAYNODE_EXTERN_C_END ASDISPLAYNODE_EXTERN_C_END
@class ASTraitCollection;
#pragma mark - ASEnvironment #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 /// Classes should implement this method and return YES / NO dependent if upward propagation is enabled or not
- (BOOL)supportsUpwardPropagation; - (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 @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 NS_ASSUME_NONNULL_END

View File

@ -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()
};
}

View 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()
};
}

View File

@ -61,7 +61,16 @@ typedef void(^ASImageCacherCompletion)(id <ASImageContainerProtocol> _Nullable i
@end @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); 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(^ASImageDownloaderProgress)(CGFloat progress);
typedef void(^ASImageDownloaderProgressImage)(UIImage *progressImage, CGFloat progress, id _Nullable downloadIdentifier); 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 URL The URL of the image to download.
@param callbackQueue The queue to call `downloadProgressBlock` and `completion` on. @param callbackQueue The queue to call `downloadProgressBlock` and `completion` on.
@param downloadProgress The block to be invoked when the download of `URL` progresses. @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 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. @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 @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. retain the identifier if you wish to use it later.
@ -109,7 +115,7 @@ typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) {
- (nullable id)downloadImageWithURL:(NSURL *)URL - (nullable id)downloadImageWithURL:(NSURL *)URL
callbackQueue:(dispatch_queue_t)callbackQueue callbackQueue:(dispatch_queue_t)callbackQueue
downloadProgress:(nullable ASImageDownloaderProgress)downloadProgress downloadProgress:(nullable ASImageDownloaderProgress)downloadProgress
completion:(nullable ASImageDownloaderCompletion)completion; completion:(ASImageDownloaderCompletion)completion;
/** /**

View File

@ -9,8 +9,12 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "ASImageProtocols.h" #import "ASImageProtocols.h"
NS_ASSUME_NONNULL_BEGIN
@interface ASPINRemoteImageDownloader : NSObject <ASImageCacheProtocol, ASImageDownloaderProtocol> @interface ASPINRemoteImageDownloader : NSObject <ASImageCacheProtocol, ASImageDownloaderProtocol>
+ (instancetype)sharedDownloader; + (ASPINRemoteImageDownloader *)sharedDownloader;
@end @end
NS_ASSUME_NONNULL_END

View File

@ -96,8 +96,9 @@
- (id <ASImageContainerProtocol>)synchronouslyFetchedCachedImageWithURL:(NSURL *)URL; - (id <ASImageContainerProtocol>)synchronouslyFetchedCachedImageWithURL:(NSURL *)URL;
{ {
NSString *key = [[self sharedPINRemoteImageManager] cacheKeyForURL:URL processorKey:nil]; PINRemoteImageManager *manager = [self sharedPINRemoteImageManager];
PINRemoteImageManagerResult *result = [[self sharedPINRemoteImageManager] synchronousImageFromCacheWithCacheKey:key options:PINRemoteImageManagerDownloadOptionsSkipDecode]; NSString *key = [manager cacheKeyForURL:URL processorKey:nil];
PINRemoteImageManagerResult *result = [manager synchronousImageFromCacheWithCacheKey:key options:PINRemoteImageManagerDownloadOptionsSkipDecode];
#if PIN_ANIMATED_AVAILABLE #if PIN_ANIMATED_AVAILABLE
if (result.alternativeRepresentation) { if (result.alternativeRepresentation) {
return result.alternativeRepresentation; return result.alternativeRepresentation;
@ -133,7 +134,18 @@
downloadProgress:(ASImageDownloaderProgress)downloadProgress downloadProgress:(ASImageDownloaderProgress)downloadProgress
completion:(ASImageDownloaderCompletion)completion; 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 we're targeting the main queue and we're on the main thread, complete immediately.
if (ASDisplayNodeThreadIsMain() && callbackQueue == dispatch_get_main_queue()) { if (ASDisplayNodeThreadIsMain() && callbackQueue == dispatch_get_main_queue()) {
#if PIN_ANIMATED_AVAILABLE #if PIN_ANIMATED_AVAILABLE

View 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

View 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

View File

@ -82,8 +82,8 @@ static void _transactionGroupRunLoopObserverCallback(CFRunLoopObserverRef observ
ASDisplayNodeAssertMainThread(); ASDisplayNodeAssertMainThread();
if ([_containerLayers count]) { if ([_containerLayers count]) {
NSHashTable *containerLayersToCommit = [_containerLayers copy]; NSHashTable *containerLayersToCommit = _containerLayers;
[_containerLayers removeAllObjects]; _containerLayers = [NSHashTable hashTableWithOptions:NSPointerFunctionsObjectPointerPersonality];
for (CALayer *containerLayer in containerLayersToCommit) { for (CALayer *containerLayer in containerLayersToCommit) {
// Note that the act of committing a transaction may open a new transaction, // Note that the act of committing a transaction may open a new transaction,

View File

@ -17,6 +17,7 @@
#import "ASInternalHelpers.h" #import "ASInternalHelpers.h"
#import "ASLayout.h" #import "ASLayout.h"
#import "ASThread.h" #import "ASThread.h"
#import "ASTraitCollection.h"
#import <objc/runtime.h> #import <objc/runtime.h>
#import <vector> #import <vector>
@ -184,6 +185,11 @@
return ASEnvironmentStatePropagationEnabled(); return ASEnvironmentStatePropagationEnabled();
} }
- (BOOL)supportsTraitsCollectionPropagation
{
return ASEnvironmentStateTraitCollectionPropagationEnabled();
}
- (void)propagateUpLayoutable:(id<ASLayoutable>)layoutable - (void)propagateUpLayoutable:(id<ASLayoutable>)layoutable
{ {
if ([layoutable isKindOfClass:[ASLayoutSpec class]]) { if ([layoutable isKindOfClass:[ASLayoutSpec class]]) {
@ -193,9 +199,20 @@
} }
} }
- (ASEnvironmentTraitCollection)environmentTraitCollection
{
return _environmentState.traitCollection;
}
ASEnvironmentLayoutOptionsForwarding ASEnvironmentLayoutOptionsForwarding
ASEnvironmentLayoutExtensibilityForwarding ASEnvironmentLayoutExtensibilityForwarding
- (ASTraitCollection *)asyncTraitCollection
{
ASDN::MutexLocker l(_propertyLock);
return [ASTraitCollection traitCollectionWithASEnvironmentTraitCollection:_environmentState.traitCollection];
}
@end @end
@implementation ASLayoutSpec (Debugging) @implementation ASLayoutSpec (Debugging)

View File

@ -228,4 +228,10 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
*/ */
- (ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass checkViewHierarchy:(BOOL)checkViewHierarchy; - (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 @end

View File

@ -13,6 +13,7 @@
#pragma once #pragma once
BOOL ASEnvironmentStatePropagationEnabled(); BOOL ASEnvironmentStatePropagationEnabled();
BOOL ASEnvironmentStateTraitCollectionPropagationEnabled();
#pragma mark - Set and get extensible values for layout options #pragma mark - Set and get extensible values for layout options
@ -45,10 +46,12 @@ static const struct ASEnvironmentStateExtensions ASEnvironmentDefaultStateExtens
static const struct ASEnvironmentLayoutOptionsState ASEnvironmentDefaultLayoutOptionsState = {}; static const struct ASEnvironmentLayoutOptionsState ASEnvironmentDefaultLayoutOptionsState = {};
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState state, ASEnvironmentStatePropagation propagation); ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState state, ASEnvironmentStatePropagation propagation);
static const struct ASEnvironmentHierarchyState ASEnvironmentDefaultHierarchyState = {}; static const struct ASEnvironmentHierarchyState ASEnvironmentDefaultHierarchyState = {};
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState state, ASEnvironmentStatePropagation propagation); ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState state, ASEnvironmentStatePropagation propagation);
static const struct ASEnvironmentTraitCollection ASEnvironmentDefaultTraitCollection = {};
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentTraitCollection state, ASEnvironmentStatePropagation propagation);
#pragma mark - Propagation #pragma mark - Propagation

View File

@ -15,13 +15,18 @@
//#define LOG(...) NSLog(__VA_ARGS__) //#define LOG(...) NSLog(__VA_ARGS__)
#define LOG(...) #define LOG(...)
#define AS_SUPPORT_PROPAGATION NO #define AS_SUPPORT_PROPAGATION YES
#define AS_DOES_NOT_SUPPORT_PROPAGATION NO
BOOL ASEnvironmentStatePropagationEnabled() BOOL ASEnvironmentStatePropagationEnabled()
{ {
return AS_SUPPORT_PROPAGATION; return AS_DOES_NOT_SUPPORT_PROPAGATION;
} }
BOOL ASEnvironmentStateTraitCollectionPropagationEnabled()
{
return AS_SUPPORT_PROPAGATION;
}
#pragma mark - Traversing an ASEnvironment Tree #pragma mark - Traversing an ASEnvironment Tree
@ -106,15 +111,15 @@ UIEdgeInsets _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(id<ASEnvir
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState hierarchyState, ASEnvironmentStatePropagation propagation) { ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState hierarchyState, ASEnvironmentStatePropagation propagation) {
// Merge object and hierarchy state // Merge object and hierarchy state
LOG(@"Merge object and state: %@ - ASEnvironmentHierarchyState", object); LOG(@"Merge object and state: %@ - ASEnvironmentHierarchyState", hierarchyState);
return environmentState; return environmentState;
} }
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState layoutOptionsState, ASEnvironmentStatePropagation propagation) { ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState layoutOptionsState, ASEnvironmentStatePropagation propagation) {
// Merge object and layout options state // 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; return environmentState;
} }
@ -188,3 +193,23 @@ ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environme
return environmentState; 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;
}

View File

@ -137,25 +137,30 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
- (void)_calculateSize - (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 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) { if (isinf(_constrainedSize.width) == NO && [_attributes.pointSizeScaleFactors count] > 0) {
_currentScaleFactor = [[self fontSizeAdjuster] scaleFactor]; _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; __block NSTextStorage *scaledTextStorage = nil;
BOOL isScaled = [self isScaled]; 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]; NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage];
[ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:_currentScaleFactor]; [ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:_currentScaleFactor];
scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString]; scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString];
[textStorage removeLayoutManager:layoutManager]; [textStorage removeLayoutManager:layoutManager];
[scaledTextStorage addLayoutManager: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]; [layoutManager ensureLayoutForTextContainer:textContainer];
}]; }];
@ -251,7 +256,9 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
- (std::vector<NSRange>)visibleRanges - (std::vector<NSRange>)visibleRanges
{ {
return [self truncater].visibleRanges; ASTextKitTailTruncater *truncater = [self truncater];
[truncater truncate];
return truncater.visibleRanges;
} }
@end @end

View File

@ -30,8 +30,6 @@
_context = context; _context = context;
_truncationAttributedString = truncationAttributedString; _truncationAttributedString = truncationAttributedString;
_avoidTailTruncationSet = avoidTailTruncationSet; _avoidTailTruncationSet = avoidTailTruncationSet;
[self _truncate];
} }
return self; return self;
} }
@ -153,7 +151,7 @@
} }
} }
- (void)_truncate - (void)truncate
{ {
[_context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { [_context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
NSUInteger originalStringLength = textStorage.length; NSUInteger originalStringLength = textStorage.length;

View File

@ -33,4 +33,9 @@
truncationAttributedString:(NSAttributedString *)truncationAttributedString truncationAttributedString:(NSAttributedString *)truncationAttributedString
avoidTailTruncationSet:(NSCharacterSet *)avoidTailTruncationSet; avoidTailTruncationSet:(NSCharacterSet *)avoidTailTruncationSet;
/**
* Actually do the truncation.
*/
- (void)truncate;
@end @end

View File

@ -53,6 +53,7 @@
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
truncationAttributedString:nil truncationAttributedString:nil
avoidTailTruncationSet:nil]; avoidTailTruncationSet:nil];
[tailTruncater truncate];
XCTAssert(NSEqualRanges(textKitVisibleRange, tailTruncater.visibleRanges[0])); XCTAssert(NSEqualRanges(textKitVisibleRange, tailTruncater.visibleRanges[0]));
} }
@ -71,6 +72,7 @@
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
truncationAttributedString:[self _simpleTruncationAttributedString] truncationAttributedString:[self _simpleTruncationAttributedString]
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@""]]; avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@""]];
[tailTruncater truncate];
__block NSString *drawnString; __block NSString *drawnString;
[context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { [context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
drawnString = textStorage.string; drawnString = textStorage.string;
@ -95,7 +97,7 @@
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
truncationAttributedString:[self _simpleTruncationAttributedString] truncationAttributedString:[self _simpleTruncationAttributedString]
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]]; avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]];
(void)tailTruncater; [tailTruncater truncate];
__block NSString *drawnString; __block NSString *drawnString;
[context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { [context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
drawnString = textStorage.string; drawnString = textStorage.string;
@ -120,8 +122,7 @@
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
truncationAttributedString:[self _simpleTruncationAttributedString] truncationAttributedString:[self _simpleTruncationAttributedString]
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]]; avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]];
// So Xcode doesn't yell at me for an unused var... [tailTruncater truncate];
(void)tailTruncater;
__block NSString *drawnString; __block NSString *drawnString;
[context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { [context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
drawnString = textStorage.string; drawnString = textStorage.string;
@ -144,9 +145,9 @@
layoutManagerDelegate:nil layoutManagerDelegate:nil
textStorageCreationBlock:nil]; textStorageCreationBlock:nil];
XCTAssertNoThrow([[ASTextKitTailTruncater alloc] initWithContext:context XCTAssertNoThrow([[[ASTextKitTailTruncater alloc] initWithContext:context
truncationAttributedString:[self _simpleTruncationAttributedString] truncationAttributedString:[self _simpleTruncationAttributedString]
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]]); avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]] truncate]);
} }
@end @end

View File

@ -44,7 +44,7 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
@interface ASTextNodeTests : XCTestCase @interface ASTextNodeTests : XCTestCase
@property (nonatomic, readwrite, strong) ASTextNode *textNode; @property (nonatomic, readwrite, strong) ASTextNode *textNode;
@property (nonatomic, readwrite, copy) NSAttributedString *attributedString; @property (nonatomic, readwrite, copy) NSAttributedString *attributedText;
@end @end
@ -80,8 +80,8 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
[mas addAttribute:NSParagraphStyleAttributeName value:lastLinePara [mas addAttribute:NSParagraphStyleAttributeName value:lastLinePara
range:NSMakeRange(mas.length - 1, 1)]; range:NSMakeRange(mas.length - 1, 1)];
_attributedString = mas; _attributedText = mas;
_textNode.attributedString = _attributedString; _textNode.attributedText = _attributedText;
} }
#pragma mark - ASTextNode #pragma mark - ASTextNode
@ -97,8 +97,8 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
- (void)testSettingTruncationMessage - (void)testSettingTruncationMessage
{ {
NSAttributedString *truncation = [[NSAttributedString alloc] initWithString:@"..." attributes:nil]; NSAttributedString *truncation = [[NSAttributedString alloc] initWithString:@"..." attributes:nil];
_textNode.truncationAttributedString = truncation; _textNode.truncationAttributedText = truncation;
XCTAssertTrue([_textNode.truncationAttributedString isEqualToAttributedString:truncation], @"Failed to set truncation message"); XCTAssertTrue([_textNode.truncationAttributedText isEqualToAttributedString:truncation], @"Failed to set truncation message");
} }
- (void)testSettingAdditionalTruncationMessage - (void)testSettingAdditionalTruncationMessage
@ -142,11 +142,11 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
- (void)testAccessibility - (void)testAccessibility
{ {
_textNode.attributedString = _attributedString; _textNode.attributedText = _attributedText;
XCTAssertTrue(_textNode.isAccessibilityElement, @"Should be an accessibility element"); 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.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 - (void)testLinkAttribute
@ -156,7 +156,7 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
NSString *linkString = @"Link"; NSString *linkString = @"Link";
NSRange linkRange = NSMakeRange(0, linkString.length); NSRange linkRange = NSMakeRange(0, linkString.length);
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:linkString attributes:@{ linkAttributeName : linkAttributeValue}]; NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:linkString attributes:@{ linkAttributeName : linkAttributeValue}];
_textNode.attributedString = attributedString; _textNode.attributedText = attributedString;
_textNode.linkAttributeNames = @[linkAttributeName]; _textNode.linkAttributeNames = @[linkAttributeName];
ASTextNodeTestDelegate *delegate = [ASTextNodeTestDelegate new]; ASTextNodeTestDelegate *delegate = [ASTextNodeTestDelegate new];
@ -178,7 +178,7 @@ static BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CGFloat delta)
NSString *linkString = @"Link notalink"; NSString *linkString = @"Link notalink";
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:linkString]; NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:linkString];
[attributedString addAttribute:linkAttributeName value:linkAttributeValue range:NSMakeRange(0, 4)]; [attributedString addAttribute:linkAttributeName value:linkAttributeValue range:NSMakeRange(0, 4)];
_textNode.attributedString = attributedString; _textNode.attributedText = attributedString;
_textNode.linkAttributeNames = @[linkAttributeName]; _textNode.linkAttributeNames = @[linkAttributeName];
ASTextNodeTestDelegate *delegate = [ASTextNodeTestDelegate new]; ASTextNodeTestDelegate *delegate = [ASTextNodeTestDelegate new];

View File

@ -23,6 +23,10 @@
#define kCFCoreFoundationVersionNumber_iOS_8_0 1140.1 #define kCFCoreFoundationVersionNumber_iOS_8_0 1140.1
#endif #endif
#ifndef kCFCoreFoundationVersionNumber_iOS_8_4
#define kCFCoreFoundationVersionNumber_iOS_8_4 1145.15
#endif
#ifndef __IPHONE_7_0 #ifndef __IPHONE_7_0
#define __IPHONE_7_0 70000 #define __IPHONE_7_0 70000
#endif #endif
@ -31,6 +35,10 @@
#define __IPHONE_8_0 80000 #define __IPHONE_8_0 80000
#endif #endif
#ifndef __IPHONE_9_0
#define __IPHONE_9_0 90000
#endif
#ifndef AS_IOS8_SDK_OR_LATER #ifndef AS_IOS8_SDK_OR_LATER
#define AS_IOS8_SDK_OR_LATER __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0 #define AS_IOS8_SDK_OR_LATER __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
#endif #endif
@ -38,3 +46,4 @@
#define AS_AT_LEAST_IOS7 (kCFCoreFoundationVersionNumber > kCFCoreFoundationVersionNumber_iOS_6_1) #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_IOS7_1 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_1)
#define AS_AT_LEAST_IOS8 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0) #define AS_AT_LEAST_IOS8 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0)
#define AS_AT_LEAST_IOS9 (kCFCoreFoundationVersionNumber > kCFCoreFoundationVersionNumber_iOS_8_4)

View File

@ -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 disclosure of security bugs. In those cases, please go through the process
outlined on that page and do not file a public issue. 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 ## Coding Style
* 2 spaces for indentation rather than tabs * 2 spaces for indentation rather than tabs

View File

@ -2,7 +2,6 @@
[![Apps Using](https://img.shields.io/badge/Apps%20Using%20ASDK-%3E3,658-28B9FE.svg)](http://cocoapods.org/pods/AsyncDisplayKit) [![Apps Using](https://img.shields.io/badge/Apps%20Using%20ASDK-%3E3,658-28B9FE.svg)](http://cocoapods.org/pods/AsyncDisplayKit)
[![Downloads](https://img.shields.io/badge/Total%20Downloads-%3E377,749-28B9FE.svg)](http://cocoapods.org/pods/AsyncDisplayKit) [![Downloads](https://img.shields.io/badge/Total%20Downloads-%3E377,749-28B9FE.svg)](http://cocoapods.org/pods/AsyncDisplayKit)
[![Slack Status](http://asdk-slack-auto-invite.herokuapp.com/badge.svg)](http://asdk-slack-auto-invite.herokuapp.com)
[![Platform](https://img.shields.io/badge/platforms-iOS%20%7C%20tvOS-orange.svg)](http://AsyncDisplayKit.org) [![Platform](https://img.shields.io/badge/platforms-iOS%20%7C%20tvOS-orange.svg)](http://AsyncDisplayKit.org)
[![Languages](https://img.shields.io/badge/languages-ObjC%20%7C%20Swift-orange.svg)](http://AsyncDisplayKit.org) [![Languages](https://img.shields.io/badge/languages-ObjC%20%7C%20Swift-orange.svg)](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) nodes](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/ASDisplayNode%2BSubclasses.h)
to implement node hierarchies or custom drawing. to implement node hierarchies or custom drawing.
### Learn more ## Learn more
* Read the [Getting Started guide](http://asyncdisplaykit.org/docs/getting-started.html) * Read the [Getting Started guide](http://asyncdisplaykit.org/docs/getting-started.html)
* Get the [sample projects](https://github.com/facebook/AsyncDisplayKit/tree/master/examples) * Get the [sample projects](https://github.com/facebook/AsyncDisplayKit/tree/master/examples)
* Browse the [API reference](http://asyncdisplaykit.org/appledocs.html) * 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) * 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 ## Testing
AsyncDisplayKit has extensive unit test coverage. You'll need to run `pod install` in the root AsyncDisplayKit directory to set up OCMock. AsyncDisplayKit has extensive unit test coverage. You'll need to run `pod install` in the root AsyncDisplayKit directory to set up OCMock.

View 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>

View File

@ -0,0 +1,3 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'AsyncDisplayKit', :path => '../..'

View 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 */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Sample.xcodeproj">
</FileRef>
</Workspace>

View File

@ -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>

View 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>

View 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

View 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

View 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

View 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

View 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>

View 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

View 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

View 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>

View 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

View 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

View 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

View 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

View 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

View 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

View 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]));
}
}

View File

@ -24,8 +24,8 @@ final class ViewController: ASViewController, ASCollectionDelegate, ASCollection
layout.minimumInteritemSpacing = padding layout.minimumInteritemSpacing = padding
layout.minimumLineSpacing = padding layout.minimumLineSpacing = padding
super.init(node: ASCollectionNode(collectionViewLayout: layout)) super.init(node: ASCollectionNode(collectionViewLayout: layout))
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Color", style: .Plain, target: self, action: "didTapColorsButton") navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Color", style: .Plain, target: self, action: #selector(didTapColorsButton))
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Layout", style: .Plain, target: self, action: "didTapLayoutButton") navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Layout", style: .Plain, target: self, action: #selector(didTapLayoutButton))
collectionNode.delegate = self collectionNode.delegate = self
collectionNode.dataSource = self collectionNode.dataSource = self
title = "Background Updating" title = "Background Updating"

View File

@ -10,101 +10,125 @@
*/ */
#import "ViewController.h" #import "ViewController.h"
#import "ASLayoutSpec.h"
#import "ASStaticLayoutSpec.h"
@interface ViewController()<ASVideoNodeDelegate> @interface ViewController()<ASVideoNodeDelegate>
@property (nonatomic, strong) ASDisplayNode *rootNode;
@property (nonatomic, strong) ASVideoNode *guitarVideoNode; @property (nonatomic, strong) ASVideoNode *guitarVideoNode;
@end @end
@implementation ViewController @implementation ViewController
#pragma mark - UIViewController
- (void)viewWillAppear:(BOOL)animated - (void)viewWillAppear:(BOOL)animated
{ {
[super viewWillAppear: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]; ASVideoNode *guitarVideoNode = self.guitarVideoNode;
[self.view addSubnode:nicCageVideo]; [_rootNode addSubnode:self.guitarVideoNode];
ASVideoNode *simonVideo = [self simonVideo]; ASVideoNode *nicCageVideoNode = self.nicCageVideoNode;
[self.view addSubnode:simonVideo]; [_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; - (ASVideoNode *)guitarVideoNode;
{ {
if (_guitarVideoNode) { if (_guitarVideoNode) {
return _guitarVideoNode; return _guitarVideoNode;
} }
_guitarVideoNode = [[ASVideoNode alloc] init]; _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.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.gravity = AVLayerVideoGravityResizeAspectFill;
_guitarVideoNode.backgroundColor = [UIColor lightGrayColor]; _guitarVideoNode.backgroundColor = [UIColor lightGrayColor];
_guitarVideoNode.periodicTimeObserverTimescale = 1; //Default is 100 _guitarVideoNode.periodicTimeObserverTimescale = 1; //Default is 100
_guitarVideoNode.delegate = self; _guitarVideoNode.delegate = self;
return _guitarVideoNode; 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; return nicCageVideoNode;
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;
} }
- (ASVideoNode *)simonVideo; - (ASVideoNode *)simonVideoNode
{ {
ASVideoNode *simonVideo = [[ASVideoNode alloc] init]; ASVideoNode *simonVideoNode = [[ASVideoNode alloc] init];
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"simon" ofType:@"mp4"]]; 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); return simonVideoNode;
simonVideo.gravity = AVLayerVideoGravityResizeAspect;
simonVideo.backgroundColor = [UIColor lightGrayColor];
simonVideo.shouldAutorepeat = YES;
simonVideo.shouldAutoplay = YES;
simonVideo.muted = YES;
return simonVideo;
} }
- (ASButtonNode *)playButton; - (ASButtonNode *)playButton;
{ {
ASButtonNode *playButton = [[ASButtonNode alloc] init]; ASButtonNode *playButtonNode = [[ASButtonNode alloc] init];
UIImage *image = [UIImage imageNamed:@"playButton@2x.png"]; UIImage *image = [UIImage imageNamed:@"playButton@2x.png"];
[playButton setImage:image forState:ASControlStateNormal]; [playButtonNode setImage:image forState:ASControlStateNormal];
[playButton measure:CGSizeMake(50, 50)]; [playButtonNode setImage:[UIImage imageNamed:@"playButtonSelected@2x.png"] forState:ASControlStateHighlighted];
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];
return playButton; // Change placement of play button if necessary
//playButtonNode.contentHorizontalAlignment = ASHorizontalAlignmentStart;
//playButtonNode.contentVerticalAlignment = ASVerticalAlignmentCenter;
return playButtonNode;
} }
#pragma mark - Actions
- (void)videoNodeWasTapped:(ASVideoNode *)videoNode - (void)videoNodeWasTapped:(ASVideoNode *)videoNode
{ {
if (videoNode == self.guitarVideoNode) { if (videoNode == self.guitarVideoNode) {
@ -125,6 +149,7 @@
} }
#pragma mark - ASVideoNodeDelegate #pragma mark - ASVideoNodeDelegate
- (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toSate - (void)videoNode:(ASVideoNode *)videoNode willChangePlayerState:(ASVideoNodePlayerState)state toState:(ASVideoNodePlayerState)toSate
{ {
//Ignore nicCageVideo //Ignore nicCageVideo