diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 8d5e02ea5d..7c880f867d 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -190,7 +190,6 @@ 25E327581C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; }; 25E327591C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; }; 2767E9411BB19BD600EA9B77 /* ASViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2767E9421BB19BD600EA9B77 /* ASViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */; }; 2911485C1A77147A005D0878 /* ASControlNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2911485B1A77147A005D0878 /* ASControlNodeTests.m */; }; 291B63FB1AA53A7A000A71B3 /* ASScrollDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 296A0A311A951715005ACEAA /* ASScrollDirection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 292C599F1A956527007E5DD6 /* ASLayoutRangeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C59991A956527007E5DD6 /* ASLayoutRangeType.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -275,8 +274,6 @@ 68EE0DC01C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */; }; 698548631CA9E025008A345F /* ASEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 698548611CA9E025008A345F /* ASEnvironment.h */; settings = {ATTRIBUTES = (Public, ); }; }; 698548641CA9E025008A345F /* ASEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 698548611CA9E025008A345F /* ASEnvironment.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 698548651CA9E025008A345F /* ASEnvironment.m in Sources */ = {isa = PBXBuildFile; fileRef = 698548621CA9E025008A345F /* ASEnvironment.m */; }; - 698548661CA9E025008A345F /* ASEnvironment.m in Sources */ = {isa = PBXBuildFile; fileRef = 698548621CA9E025008A345F /* ASEnvironment.m */; }; 698C8B611CAB49FC0052DC3F /* ASLayoutableExtensibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 698C8B601CAB49FC0052DC3F /* ASLayoutableExtensibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; 698C8B621CAB49FC0052DC3F /* ASLayoutableExtensibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 698C8B601CAB49FC0052DC3F /* ASLayoutableExtensibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; 69CB62AB1CB8165900024920 /* _ASDisplayViewAccessiblity.h in Headers */ = {isa = PBXBuildFile; fileRef = 69CB62A91CB8165900024920 /* _ASDisplayViewAccessiblity.h */; }; @@ -336,6 +333,9 @@ 9C8898BD1C738BB800D6B02E /* ASTextKitFontSizeAdjuster.h in Headers */ = {isa = PBXBuildFile; fileRef = A32FEDD31C501B6A004F642A /* ASTextKitFontSizeAdjuster.h */; }; 9CDC18CC1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9CDC18CD1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9CFFC6BE1CCAC52B006A6476 /* ASEnvironment.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */; }; + 9CFFC6C01CCAC73C006A6476 /* ASViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */; }; + 9CFFC6C21CCAC768006A6476 /* ASTableNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */; }; 9F06E5CD1B4CAF4200F015D8 /* ASCollectionViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */; }; A2763D791CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */; }; A2763D7A1CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */; }; @@ -362,7 +362,6 @@ AC7A2C171BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */; }; AC7A2C181BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */; }; ACC945A91BA9E7A0005E1FB8 /* ASViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - ACC945AB1BA9E7C1005E1FB8 /* ASViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */; }; ACF6ED1A1B17843500DA7C62 /* ASBackgroundLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED011B17843500DA7C62 /* ASBackgroundLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; ACF6ED1B1B17843500DA7C62 /* ASBackgroundLayoutSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED021B17843500DA7C62 /* ASBackgroundLayoutSpec.mm */; }; ACF6ED1C1B17843500DA7C62 /* ASCenterLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED031B17843500DA7C62 /* ASCenterLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -405,7 +404,6 @@ AEEC47E21C20C2DD00EC1693 /* ASVideoNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E01C20C2DD00EC1693 /* ASVideoNode.mm */; }; AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */; }; B0F8805A1BEAEC7500D17647 /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B0F8805B1BEAEC7500D17647 /* ASTableNode.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F880591BEAEC7500D17647 /* ASTableNode.m */; }; B13CA0F71C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0F61C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; B13CA0F81C519EBA00E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0F61C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; B13CA1001C52004900E031AB /* ASCollectionNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -499,7 +497,6 @@ B350625D1B0111740018CF92 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943141A1575670030A7D0 /* Photos.framework */; }; B350625E1B0111780018CF92 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943121A1575630030A7D0 /* AssetsLibrary.framework */; }; B350625F1B0111800018CF92 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AF195D04C000B7D73C /* Foundation.framework */; }; - C78F7E2A1BF7808300CDEAFC /* ASTableNode.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F880591BEAEC7500D17647 /* ASTableNode.m */; }; C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC3B20831C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; }; CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; }; @@ -779,7 +776,6 @@ 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMainSerialQueue.h; sourceTree = ""; }; 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMainSerialQueue.mm; sourceTree = ""; }; 698548611CA9E025008A345F /* ASEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEnvironment.h; sourceTree = ""; }; - 698548621CA9E025008A345F /* ASEnvironment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASEnvironment.m; sourceTree = ""; }; 698C8B601CAB49FC0052DC3F /* ASLayoutableExtensibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutableExtensibility.h; path = AsyncDisplayKit/Layout/ASLayoutableExtensibility.h; sourceTree = ""; }; 69CB62A91CB8165900024920 /* _ASDisplayViewAccessiblity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASDisplayViewAccessiblity.h; sourceTree = ""; }; 69CB62AA1CB8165900024920 /* _ASDisplayViewAccessiblity.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASDisplayViewAccessiblity.mm; sourceTree = ""; }; @@ -809,6 +805,9 @@ 9C8221941BA237B80037F19A /* ASStackBaselinePositionedLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackBaselinePositionedLayout.mm; sourceTree = ""; }; 9C8898BA1C738B9800D6B02E /* ASTextKitFontSizeAdjuster.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitFontSizeAdjuster.mm; path = TextKit/ASTextKitFontSizeAdjuster.mm; sourceTree = ""; }; 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutablePrivate.h; path = AsyncDisplayKit/Layout/ASLayoutablePrivate.h; sourceTree = ""; }; + 9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEnvironment.mm; sourceTree = ""; }; + 9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASViewController.mm; sourceTree = ""; }; + 9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTableNode.mm; sourceTree = ""; }; 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASCollectionViewTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASPINRemoteImageDownloader.h; path = Details/ASPINRemoteImageDownloader.h; sourceTree = ""; }; A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASPINRemoteImageDownloader.m; path = Details/ASPINRemoteImageDownloader.m; sourceTree = ""; }; @@ -828,7 +827,6 @@ AC6456071B0A335000CF11B8 /* ASCellNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCellNode.mm; sourceTree = ""; }; AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTableViewInternal.h; sourceTree = ""; }; ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASViewController.h; sourceTree = ""; }; - ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASViewController.m; sourceTree = ""; }; ACF6ED011B17843500DA7C62 /* ASBackgroundLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASBackgroundLayoutSpec.h; path = AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h; sourceTree = ""; }; ACF6ED021B17843500DA7C62 /* ASBackgroundLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; name = ASBackgroundLayoutSpec.mm; path = AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm; sourceTree = ""; }; ACF6ED031B17843500DA7C62 /* ASCenterLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASCenterLayoutSpec.h; path = AsyncDisplayKit/Layout/ASCenterLayoutSpec.h; sourceTree = ""; }; @@ -872,7 +870,6 @@ AEEC47E01C20C2DD00EC1693 /* ASVideoNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASVideoNode.mm; sourceTree = ""; }; AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASVideoNodeTests.m; sourceTree = ""; }; B0F880581BEAEC7500D17647 /* ASTableNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTableNode.h; sourceTree = ""; }; - B0F880591BEAEC7500D17647 /* ASTableNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableNode.m; sourceTree = ""; }; B13CA0F61C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionViewLayoutFacilitatorProtocol.h; sourceTree = ""; }; B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionNode+Beta.h"; sourceTree = ""; }; B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutManager.h; path = TextKit/ASLayoutManager.h; sourceTree = ""; }; @@ -1073,7 +1070,7 @@ D785F6601A74327E00291744 /* ASScrollNode.h */, D785F6611A74327E00291744 /* ASScrollNode.m */, B0F880581BEAEC7500D17647 /* ASTableNode.h */, - B0F880591BEAEC7500D17647 /* ASTableNode.m */, + 9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */, 055F1A3219ABD3E3004DAFF1 /* ASTableView.h */, 055F1A3319ABD3E3004DAFF1 /* ASTableView.mm */, AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */, @@ -1082,7 +1079,7 @@ A373200E1C571B050011FC94 /* ASTextNode+Beta.h */, 058D09E0195D050800B7D73C /* ASTextNode.mm */, ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */, - ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */, + 9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */, 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */, 764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */, 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */, @@ -1167,6 +1164,7 @@ 058D09E1195D050800B7D73C /* Details */ = { isa = PBXGroup; children = ( + 9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */, 058D09E2195D050800B7D73C /* _ASDisplayLayer.h */, 058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */, 058D09E4195D050800B7D73C /* _ASDisplayView.h */, @@ -1187,7 +1185,6 @@ 05A6D05819D0EB64002DD95E /* ASDealloc2MainObject.h */, 05A6D05919D0EB64002DD95E /* ASDealloc2MainObject.m */, 698548611CA9E025008A345F /* ASEnvironment.h */, - 698548621CA9E025008A345F /* ASEnvironment.m */, 4640521B1A3F83C40061C0BA /* ASFlowLayoutController.h */, 4640521C1A3F83C40061C0BA /* ASFlowLayoutController.mm */, 058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */, @@ -1982,6 +1979,7 @@ 92DD2FE41BF4B97E0074C9DD /* ASMapNode.mm in Sources */, DBC452DC1C5BF64600B16017 /* NSArray+Diffing.m in Sources */, AC3C4A521A1139C100143C57 /* ASCollectionView.mm in Sources */, + 9CFFC6C21CCAC768006A6476 /* ASTableNode.mm in Sources */, 205F0E1E1B373A2C007741D0 /* ASCollectionViewLayoutController.mm in Sources */, 058D0A13195D050800B7D73C /* ASControlNode.mm in Sources */, 464052211A3F83C40061C0BA /* ASDataController.mm in Sources */, @@ -2007,7 +2005,6 @@ 430E7C911B4C23F100697A4C /* ASIndexPath.m in Sources */, ACF6ED231B17843500DA7C62 /* ASInsetLayoutSpec.mm in Sources */, ACF6ED4C1B17847A00DA7C62 /* ASInternalHelpers.mm in Sources */, - 698548651CA9E025008A345F /* ASEnvironment.m in Sources */, ACF6ED251B17843500DA7C62 /* ASLayout.mm in Sources */, DB55C2631C6408D6004EDCF5 /* _ASTransitionContext.m in Sources */, 92074A631CC8BA1900918F75 /* ASImageNode+tvOS.m in Sources */, @@ -2050,13 +2047,13 @@ ACF6ED321B17843500DA7C62 /* ASStaticLayoutSpec.mm in Sources */, AC026B6B1BD57D6F00BBC17E /* ASChangeSetDataController.m in Sources */, 68355B311CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */, + 9CFFC6C01CCAC73C006A6476 /* ASViewController.mm in Sources */, 055F1A3519ABD3E3004DAFF1 /* ASTableView.mm in Sources */, 058D0A17195D050800B7D73C /* ASTextNode.mm in Sources */, 257754AC1BEE44CD00737CA5 /* ASTextKitRenderer.mm in Sources */, - ACC945AB1BA9E7C1005E1FB8 /* ASViewController.m in Sources */, - B0F8805B1BEAEC7500D17647 /* ASTableNode.m in Sources */, 205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */, 257754B21BEE44CD00737CA5 /* ASTextKitShadower.mm in Sources */, + 9CFFC6BE1CCAC52B006A6476 /* ASEnvironment.mm in Sources */, 058D0A21195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m in Sources */, 205F0E101B371875007741D0 /* UICollectionViewLayout+ASConvenience.m in Sources */, CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */, @@ -2121,8 +2118,6 @@ B35062421B010EFD0018CF92 /* _ASAsyncTransactionGroup.m in Sources */, B350624A1B010EFD0018CF92 /* _ASCoreAnimationExtras.mm in Sources */, 68EE0DC01C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */, - 698548661CA9E025008A345F /* ASEnvironment.m in Sources */, - 2767E9421BB19BD600EA9B77 /* ASViewController.m in Sources */, B35062101B010EFD0018CF92 /* _ASDisplayLayer.mm in Sources */, 9C55866B1BD54A1900B50E3A /* ASAsciiArtBoxCreator.m in Sources */, B35062121B010EFD0018CF92 /* _ASDisplayView.mm in Sources */, @@ -2207,7 +2202,6 @@ B350620B1B010EFD0018CF92 /* ASTableView.mm in Sources */, B350620E1B010EFD0018CF92 /* ASTextNode.mm in Sources */, 68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */, - C78F7E2A1BF7808300CDEAFC /* ASTableNode.m in Sources */, 509E68661B3AEDD7009B9150 /* CGRect+ASConvenience.m in Sources */, 254C6B8D1BF94F8A003EC431 /* ASEqualityHashHelpers.mm in Sources */, 254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.m in Sources */, diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index d33ef7bb0d..6a6a1ead2e 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -10,6 +10,7 @@ #import "ASCollectionInternal.h" #import "ASCollectionViewLayoutFacilitatorProtocol.h" #import "ASDisplayNode+Subclasses.h" +#import "ASEnvironmentInternal.h" #import "ASRangeControllerUpdateRangeProtocol+Beta.h" #include @@ -244,4 +245,6 @@ [self.view reloadDataImmediately]; } +ASDisplayTraitsCollectionTableSetEnvironmentState + @end diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index b5a246e794..c379f3cbce 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -91,7 +91,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; #pragma mark - #pragma mark ASCollectionView. -@interface ASCollectionView () { +@interface ASCollectionView () { ASCollectionViewProxy *_proxyDataSource; ASCollectionViewProxy *_proxyDelegate; @@ -225,6 +225,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; _dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:NO]; _dataController.delegate = _rangeController; _dataController.dataSource = self; + _dataController.environmentDelegate = self; _batchContext = [[ASBatchContext alloc] init]; @@ -917,6 +918,14 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; } } +- (id)dataControllerEnvironment +{ + if (self.collectionNode) { + return self.collectionNode; + } + return self.strongCollectionNode; +} + #pragma mark - ASCollectionViewDataControllerSource Supplementary view support - (ASCellNode *)dataController:(ASCollectionDataController *)dataController supplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 6e54a450c1..3cbb57add1 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -2687,11 +2687,13 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority"; - (ASEnvironmentState)environmentState { + ASDN::MutexLocker l(_propertyLock); return _environmentState; } - (void)setEnvironmentState:(ASEnvironmentState)environmentState { + ASDN::MutexLocker l(_propertyLock); _environmentState = environmentState; } @@ -2707,7 +2709,12 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority"; - (BOOL)supportsUpwardPropagation { - return ASEnvironmentStatePropagationEnabled(); + return ASEnvironmentStateUpwardPropagationEnabled(); +} + +- (BOOL)supportsDownwardPropagation +{ + return ASEnvironmentStateDownwardPropagationEnabled(); } ASEnvironmentLayoutOptionsForwarding diff --git a/AsyncDisplayKit/ASTableNode.m b/AsyncDisplayKit/ASTableNode.mm similarity index 97% rename from AsyncDisplayKit/ASTableNode.m rename to AsyncDisplayKit/ASTableNode.mm index 22b6c3926f..16cf1cad9e 100644 --- a/AsyncDisplayKit/ASTableNode.m +++ b/AsyncDisplayKit/ASTableNode.mm @@ -6,6 +6,7 @@ // Copyright © 2015 Facebook. All rights reserved. // +#import "ASEnvironmentInternal.h" #import "ASFlowLayoutController.h" #import "ASTableViewInternal.h" #import "ASDisplayNode+Subclasses.h" @@ -158,4 +159,6 @@ [self.view clearFetchedData]; } +ASDisplayTraitsCollectionTableSetEnvironmentState + @end diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 59066323bd..214883b524 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -16,6 +16,7 @@ #import "ASDisplayNodeExtras.h" #import "ASDisplayNode+Beta.h" #import "ASDisplayNode+FrameworkPrivate.h" +#import "ASEnvironmentInternal.h" #import "ASInternalHelpers.h" #import "ASLayout.h" #import "ASLayoutController.h" @@ -88,7 +89,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; - (instancetype)_initWithTableView:(ASTableView *)tableView; @end -@interface ASTableView () +@interface ASTableView () { ASTableViewProxy *_proxyDataSource; ASTableViewProxy *_proxyDelegate; @@ -175,6 +176,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; _dataController = [[dataControllerClass alloc] initWithAsyncDataFetching:NO]; _dataController.dataSource = self; _dataController.delegate = _rangeController; + _dataController.environmentDelegate = self; _layoutController.dataSource = _dataController; @@ -1078,6 +1080,16 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; } } +#pragma mark - ASDataControllerEnvironmentDelegate + +- (id)dataControllerEnvironment +{ + if (self.tableNode) { + return self.tableNode; + } + return self.strongTableNode; +} + #pragma mark - _ASTableViewCellDelegate - (void)didLayoutSubviewsOfTableViewCell:(_ASTableViewCell *)tableViewCell diff --git a/AsyncDisplayKit/ASViewController.h b/AsyncDisplayKit/ASViewController.h index d7286272b8..036cea4236 100644 --- a/AsyncDisplayKit/ASViewController.h +++ b/AsyncDisplayKit/ASViewController.h @@ -11,12 +11,27 @@ NS_ASSUME_NONNULL_BEGIN +typedef ASDisplayTraits (^ASDisplayTraitsForTraitCollectionBlock)(UITraitCollection *traitCollection); +typedef ASDisplayTraits (^ASDisplayTraitsForTraitWindowSizeBlock)(CGSize windowSize); + @interface ASViewController<__covariant DisplayNodeType : ASDisplayNode *> : UIViewController - (instancetype)initWithNode:(DisplayNodeType)node NS_DESIGNATED_INITIALIZER; @property (nonatomic, strong, readonly) DisplayNodeType node; +@property (nonatomic, strong) id displayTraitsContext; + +/** + * Set this block to customize the ASDisplayTraits returned when the VC transitions to the given traitCollection. + */ +@property (nonatomic, copy) ASDisplayTraitsForTraitCollectionBlock overrideDisplayTraitsWithTraitCollection; + +/** + * Set this block to customize the ASDisplayTraits returned when the VC transitions to the given window size. + */ +@property (nonatomic, copy) ASDisplayTraitsForTraitWindowSizeBlock overrideDisplayTraitsWithWindowSize; + /** * @abstract Passthrough property to the the .interfaceState of the node. * @return The current ASInterfaceState of the node, indicating whether it is visible and other situational properties. diff --git a/AsyncDisplayKit/ASViewController.m b/AsyncDisplayKit/ASViewController.mm similarity index 59% rename from AsyncDisplayKit/ASViewController.m rename to AsyncDisplayKit/ASViewController.mm index db5b1e5b4d..bf48a39862 100644 --- a/AsyncDisplayKit/ASViewController.m +++ b/AsyncDisplayKit/ASViewController.mm @@ -11,6 +11,7 @@ #import "ASDimension.h" #import "ASDisplayNode+FrameworkPrivate.h" #import "ASDisplayNode+Beta.h" +#import "ASEnvironmentInternal.h" #import "ASRangeControllerUpdateRangeProtocol+Beta.h" @implementation ASViewController @@ -42,10 +43,18 @@ _node = node; _automaticallyAdjustRangeModeBasedOnViewEvents = NO; - + return self; } +- (void)dealloc +{ + if (_displayTraitsContext != nil) { + ASDisplayTraitsClearDisplayContext(self.node); + _displayTraitsContext = nil; + } +} + - (void)loadView { ASDisplayNodeAssertTrue(!_node.layerBacked); @@ -132,4 +141,66 @@ return _node.interfaceState; } +#pragma mark - ASDisplayTraits + +- (ASDisplayTraits)displayTraitsForTraitCollection:(UITraitCollection *)traitCollection +{ + if (self.overrideDisplayTraitsWithTraitCollection) { + return self.overrideDisplayTraitsWithTraitCollection(traitCollection); + } + + ASDisplayTraits displayTraits = ASDisplayTraitsFromUITraitCollection(traitCollection); + displayTraits.displayContext = _displayTraitsContext; + return displayTraits; +} + +- (ASDisplayTraits)displayTraitsForWindowSize:(CGSize)windowSize +{ + if (self.overrideDisplayTraitsWithWindowSize) { + return self.overrideDisplayTraitsWithWindowSize(windowSize); + } + return self.node.environmentState.displayTraits; +} + +- (void)progagateNewDisplayTraits:(ASDisplayTraits)displayTraits +{ + ASEnvironmentState environmentState = self.node.environmentState; + ASDisplayTraits oldDisplayTraits = environmentState.displayTraits; + + if (ASDisplayTraitsIsEqualToASDisplayTraits(displayTraits, oldDisplayTraits) == NO) { + environmentState.displayTraits = displayTraits; + [self.node setEnvironmentState:environmentState]; + [self.node setNeedsLayout]; + + NSArray> *children = [self.node children]; + for (id child in children) { + ASEnvironmentStatePropagateDown(child, environmentState.displayTraits); + } + } +} + +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection +{ + [super traitCollectionDidChange:previousTraitCollection]; + + ASDisplayTraits displayTraits = [self displayTraitsForTraitCollection:self.traitCollection]; + [self progagateNewDisplayTraits:displayTraits]; +} + +- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id)coordinator +{ + [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator]; + + ASDisplayTraits displayTraits = [self displayTraitsForTraitCollection:self.traitCollection]; + [self progagateNewDisplayTraits:displayTraits]; +} + +- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator +{ + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; + + ASDisplayTraits displayTraits = [self displayTraitsForWindowSize:size]; + [self progagateNewDisplayTraits:displayTraits]; +} + @end diff --git a/AsyncDisplayKit/Details/ASDataController.h b/AsyncDisplayKit/Details/ASDataController.h index 190119ed62..7ca8caf323 100644 --- a/AsyncDisplayKit/Details/ASDataController.h +++ b/AsyncDisplayKit/Details/ASDataController.h @@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN @class ASCellNode; @class ASDataController; +@protocol ASEnvironment; typedef NSUInteger ASDataControllerAnimationOptions; @@ -64,6 +65,11 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind; */ - (void)dataControllerUnlockDataSource; + +@end + +@protocol ASDataControllerEnvironmentDelegate +- (id)dataControllerEnvironment; @end /** @@ -122,6 +128,11 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind; */ @property (nonatomic, weak) id delegate; +/** + * + */ +@property (nonatomic, weak) id environmentDelegate; + /** * Designated initializer. * diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index b84adeda48..55b43a4d71 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -13,6 +13,7 @@ #import "ASAssert.h" #import "ASCellNode.h" #import "ASDisplayNode.h" +#import "ASEnvironmentInternal.h" #import "ASFlowLayoutController.h" #import "ASInternalHelpers.h" #import "ASLayout.h" @@ -519,8 +520,17 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; for (NSUInteger i = 0; i < rowNum; i++) { NSIndexPath *indexPath = [sectionIndex indexPathByAddingIndex:i]; ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath]; + + // When creating a node, make sure to pass along the current display traits so it will be laid out properly + ASCellNodeBlock nodeBlockPropagatingDisplayTraits = ^{ + ASCellNode *cellNode = nodeBlock(); + id environment = [self.environmentDelegate dataControllerEnvironment]; + ASEnvironmentStatePropagateDown(cellNode, [environment environmentState].displayTraits); + return cellNode; + }; + ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:ASDataControllerRowNodeKind atIndexPath:indexPath]; - [contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlock + [contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlockPropagatingDisplayTraits indexPath:indexPath constrainedSize:constrainedSize]]; } diff --git a/AsyncDisplayKit/Details/ASEnvironment.h b/AsyncDisplayKit/Details/ASEnvironment.h index 8c473cc08c..c918d18f51 100644 --- a/AsyncDisplayKit/Details/ASEnvironment.h +++ b/AsyncDisplayKit/Details/ASEnvironment.h @@ -14,6 +14,8 @@ #import "ASStackLayoutDefines.h" #import "ASRelativeSize.h" +@protocol ASEnvironment; +@class UITraitCollection; ASDISPLAYNODE_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -59,17 +61,50 @@ typedef struct ASEnvironmentHierarchyState { unsigned layoutPending:1; // = NO } ASEnvironmentHierarchyState; +#pragma mark - ASDisplayTraits + +typedef struct ASDisplayTraits { + 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 + // trait collcetion 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. + // + // An added precaution is to call ASDisplayTraitsClearDisplayContext from your ASVC's desctructor + // which will propagate a nil displayContext to its subnodes. + //__unsafe_unretained id displayContext; + id __unsafe_unretained displayContext; +} ASDisplayTraits; + +extern void ASDisplayTraitsClearDisplayContext(id rootEnvironment); + +extern ASDisplayTraits ASDisplayTraitsFromUITraitCollection(UITraitCollection *traitCollection); +extern BOOL ASDisplayTraitsIsEqualToASDisplayTraits(ASDisplayTraits displayTraits0, ASDisplayTraits displayTraits1); #pragma mark - ASEnvironmentState typedef struct ASEnvironmentState { struct ASEnvironmentHierarchyState hierarchyState; struct ASEnvironmentLayoutOptionsState layoutOptionsState; + struct ASDisplayTraits displayTraits; } ASEnvironmentState; extern ASEnvironmentState ASEnvironmentStateMakeDefault(); ASDISPLAYNODE_EXTERN_C_END +@class ASTraitCollection; #pragma mark - ASEnvironment @@ -93,6 +128,33 @@ ASDISPLAYNODE_EXTERN_C_END /// Classes should implement this method and return YES / NO dependent if upward propagation is enabled or not - (BOOL)supportsUpwardPropagation; +/// Classes should implement this method and return YES / NO dependent if downware propagation is enabled or not +- (BOOL)supportsDownwardPropagation; + @end -NS_ASSUME_NONNULL_END \ No newline at end of file +// 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 ASDisplayTraitsCollectionTableSetEnvironmentState \ +- (void)setEnvironmentState:(ASEnvironmentState)environmentState\ +{\ + ASDisplayTraits oldDisplayTraits = self.environmentState.displayTraits;\ + [super setEnvironmentState:environmentState];\ + ASDisplayTraits currentDisplayTraits = environmentState.displayTraits;\ + if (ASDisplayTraitsIsEqualToASDisplayTraits(currentDisplayTraits, oldDisplayTraits) == NO) {\ + NSArray *> *completedNodes = [self.view.dataController completedNodes];\ + for (NSArray *sectionArray in completedNodes) {\ + for (ASCellNode *cellNode in sectionArray) {\ + ASEnvironmentStatePropagateDown(cellNode, currentDisplayTraits);\ + [cellNode setNeedsLayout];\ + }\ + }\ + }\ +}\ + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASEnvironment.m b/AsyncDisplayKit/Details/ASEnvironment.m deleted file mode 100644 index f3b2039f8f..0000000000 --- a/AsyncDisplayKit/Details/ASEnvironment.m +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ - -#import "ASEnvironment.h" - -ASEnvironmentLayoutOptionsState _ASEnvironmentLayoutOptionsStateMakeDefault() -{ - return (ASEnvironmentLayoutOptionsState) { - // Default values can be defined in here - }; -} - -ASEnvironmentHierarchyState _ASEnvironmentHierarchyStateMakeDefault() -{ - return (ASEnvironmentHierarchyState) { - // Default values can be defined in here - }; -} - -ASEnvironmentState ASEnvironmentStateMakeDefault() -{ - return (ASEnvironmentState) { - .layoutOptionsState = _ASEnvironmentLayoutOptionsStateMakeDefault(), - .hierarchyState = _ASEnvironmentHierarchyStateMakeDefault() - }; -} \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASEnvironment.mm b/AsyncDisplayKit/Details/ASEnvironment.mm new file mode 100644 index 0000000000..1439c8200f --- /dev/null +++ b/AsyncDisplayKit/Details/ASEnvironment.mm @@ -0,0 +1,77 @@ +/* + * 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" + +ASEnvironmentLayoutOptionsState _ASEnvironmentLayoutOptionsStateMakeDefault() +{ + return (ASEnvironmentLayoutOptionsState) { + // Default values can be defined in here + }; +} + +ASEnvironmentHierarchyState _ASEnvironmentHierarchyStateMakeDefault() +{ + return (ASEnvironmentHierarchyState) { + // Default values can be defined in here + }; +} + +extern void ASDisplayTraitsClearDisplayContext(id rootEnvironment) +{ + ASEnvironmentState envState = [rootEnvironment environmentState]; + ASDisplayTraits displayTraits = envState.displayTraits; + displayTraits.displayContext = nil; + envState.displayTraits = displayTraits; + [rootEnvironment setEnvironmentState:envState]; + + for (id child in [rootEnvironment children]) { + ASEnvironmentStatePropagateDown(child, displayTraits); + } +} + +ASDisplayTraits _ASDisplayTraitsMakeDefault() +{ + return (ASDisplayTraits) { + // Default values can be defined in here + }; +} + +ASDisplayTraits ASDisplayTraitsFromUITraitCollection(UITraitCollection *traitCollection) +{ + return (ASDisplayTraits) { + .displayScale = traitCollection.displayScale, + .horizontalSizeClass = traitCollection.horizontalSizeClass, + .userInterfaceIdiom = traitCollection.userInterfaceIdiom, + .verticalSizeClass = traitCollection.verticalSizeClass, + .forceTouchCapability = traitCollection.forceTouchCapability, + }; +} + +BOOL ASDisplayTraitsIsEqualToASDisplayTraits(ASDisplayTraits displayTraits0, ASDisplayTraits displayTraits1) +{ + return + displayTraits0.verticalSizeClass == displayTraits1.verticalSizeClass && + displayTraits0.horizontalSizeClass == displayTraits1.horizontalSizeClass && + displayTraits0.displayScale == displayTraits1.displayScale && + displayTraits0.userInterfaceIdiom == displayTraits1.userInterfaceIdiom && + displayTraits0.forceTouchCapability == displayTraits1.forceTouchCapability; +} + +ASEnvironmentState ASEnvironmentStateMakeDefault() +{ + return (ASEnvironmentState) { + .layoutOptionsState = _ASEnvironmentLayoutOptionsStateMakeDefault(), + .hierarchyState = _ASEnvironmentHierarchyStateMakeDefault(), + .displayTraits = _ASDisplayTraitsMakeDefault() + }; +} + diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index d5830d0c79..48f15bfc17 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -80,7 +80,7 @@ id finalLayoutable = [child finalLayoutable]; if (finalLayoutable != child) { - if (ASEnvironmentStatePropagationEnabled()) { + if (ASEnvironmentStateUpwardPropagationEnabled()) { ASEnvironmentStatePropagateUp(finalLayoutable, child.environmentState.layoutOptionsState); } else { // If state propagation is not enabled the layout options state needs to be copied manually @@ -168,11 +168,13 @@ - (ASEnvironmentState)environmentState { + ASDN::MutexLocker l(_propertyLock); return _environmentState; } - (void)setEnvironmentState:(ASEnvironmentState)environmentState { + ASDN::MutexLocker l(_propertyLock); _environmentState = environmentState; } @@ -181,7 +183,12 @@ // the specifications that are known to have more than one. - (BOOL)supportsUpwardPropagation { - return ASEnvironmentStatePropagationEnabled(); + return ASEnvironmentStateUpwardPropagationEnabled(); +} + +- (BOOL)supportsDownwardPropagation +{ + return ASEnvironmentStateDownwardPropagationEnabled(); } - (void)propagateUpLayoutable:(id)layoutable diff --git a/AsyncDisplayKit/Layout/ASLayoutablePrivate.h b/AsyncDisplayKit/Layout/ASLayoutablePrivate.h index f218e41725..1ca166c7f0 100644 --- a/AsyncDisplayKit/Layout/ASLayoutablePrivate.h +++ b/AsyncDisplayKit/Layout/ASLayoutablePrivate.h @@ -79,7 +79,7 @@ extern void ASLayoutableClearCurrentContext(); #define ASEnvironmentLayoutOptionsForwarding \ - (void)propagateUpLayoutOptionsState\ {\ - if (!ASEnvironmentStatePropagationEnabled()) {\ + if (!ASEnvironmentStateUpwardPropagationEnabled()) {\ return;\ }\ id parent = [self parent];\ diff --git a/AsyncDisplayKit/Private/ASEnvironmentInternal.h b/AsyncDisplayKit/Private/ASEnvironmentInternal.h index 9bd2c305d4..adfefcc70d 100644 --- a/AsyncDisplayKit/Private/ASEnvironmentInternal.h +++ b/AsyncDisplayKit/Private/ASEnvironmentInternal.h @@ -12,7 +12,8 @@ #pragma once -BOOL ASEnvironmentStatePropagationEnabled(); +BOOL ASEnvironmentStateUpwardPropagationEnabled(); +BOOL ASEnvironmentStateDownwardPropagationEnabled(); #pragma mark - Set and get extensible values for layout options @@ -45,10 +46,12 @@ static const struct ASEnvironmentStateExtensions ASEnvironmentDefaultStateExtens static const struct ASEnvironmentLayoutOptionsState ASEnvironmentDefaultLayoutOptionsState = {}; ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState state, ASEnvironmentStatePropagation propagation); - static const struct ASEnvironmentHierarchyState ASEnvironmentDefaultHierarchyState = {}; ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState state, ASEnvironmentStatePropagation propagation); +static const struct ASDisplayTraits ASEnvironmentDefaultDisplayTraits = {}; +ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASDisplayTraits state, ASEnvironmentStatePropagation propagation); + #pragma mark - Propagation diff --git a/AsyncDisplayKit/Private/ASEnvironmentInternal.mm b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm index 83ea991b85..b22ab3ee97 100644 --- a/AsyncDisplayKit/Private/ASEnvironmentInternal.mm +++ b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm @@ -15,11 +15,17 @@ //#define LOG(...) NSLog(__VA_ARGS__) #define LOG(...) -#define AS_SUPPORT_PROPAGATION NO +#define AS_SUPPORT_UPWARD_PROPAGATION NO +#define AS_SUPPORT_DOWNWARD_PROPAGATION YES -BOOL ASEnvironmentStatePropagationEnabled() +BOOL ASEnvironmentStateUpwardPropagationEnabled() { - return AS_SUPPORT_PROPAGATION; + return AS_SUPPORT_UPWARD_PROPAGATION; +} + +BOOL ASEnvironmentStateDownwardPropagationEnabled() +{ + return AS_SUPPORT_DOWNWARD_PROPAGATION; } @@ -106,15 +112,15 @@ UIEdgeInsets _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(id '../..' diff --git a/examples/DisplayTraits/Sample.xcodeproj/project.pbxproj b/examples/DisplayTraits/Sample.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..b46865ed75 --- /dev/null +++ b/examples/DisplayTraits/Sample.xcodeproj/project.pbxproj @@ -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 = ""; }; + 05E2128619D4DB510098F589 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 05E2128819D4DB510098F589 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 05E2128919D4DB510098F589 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 05E2128B19D4DB510098F589 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 05E2128C19D4DB510098F589 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; + 9CACC77F1CCEAF9E009A1613 /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = ""; }; + 9CACC7801CCEAF9E009A1613 /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = ""; }; + 9CACC7821CCEAFAE009A1613 /* CollectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionViewController.h; sourceTree = ""; }; + 9CACC7831CCEAFAE009A1613 /* CollectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CollectionViewController.m; sourceTree = ""; }; + 9CACC7851CCEBD3B009A1613 /* KittenNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KittenNode.h; sourceTree = ""; }; + 9CACC7861CCEBD3B009A1613 /* KittenNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KittenNode.m; sourceTree = ""; }; + 9CACC7881CCEC82C009A1613 /* OverrideViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OverrideViewController.h; sourceTree = ""; }; + 9CACC7891CCEC82C009A1613 /* OverrideViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OverrideViewController.m; sourceTree = ""; }; + 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 = ""; }; +/* 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 = ""; + tabWidth = 2; + usesTabs = 0; + }; + 05E2128219D4DB510098F589 /* Products */ = { + isa = PBXGroup; + children = ( + 05E2128119D4DB510098F589 /* Sample.app */, + ); + name = Products; + sourceTree = ""; + }; + 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 = ""; + }; + 05E2128419D4DB510098F589 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 05E2128519D4DB510098F589 /* Info.plist */, + 05E2128619D4DB510098F589 /* main.m */, + 9C37D01D1CC94BC9004C8BC1 /* Launch Screen.storyboard */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A943BF0259746F18D6E423F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3D24B17D1E4A4E7A9566C5E9 /* libPods.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 1AE410B73DA5C3BD087ACDD7 /* Pods */ = { + isa = PBXGroup; + children = ( + C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */, + 088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; +/* 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 */; +} diff --git a/examples/DisplayTraits/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/DisplayTraits/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..a80c038249 --- /dev/null +++ b/examples/DisplayTraits/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/DisplayTraits/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme b/examples/DisplayTraits/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme new file mode 100644 index 0000000000..1e14aa0329 --- /dev/null +++ b/examples/DisplayTraits/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/DisplayTraits/Sample.xcworkspace/contents.xcworkspacedata b/examples/DisplayTraits/Sample.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..7b5a2f3050 --- /dev/null +++ b/examples/DisplayTraits/Sample.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/examples/DisplayTraits/Sample/AppDelegate.h b/examples/DisplayTraits/Sample/AppDelegate.h new file mode 100644 index 0000000000..85855277e9 --- /dev/null +++ b/examples/DisplayTraits/Sample/AppDelegate.h @@ -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 + +#define UseAutomaticLayout 1 + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/examples/DisplayTraits/Sample/AppDelegate.m b/examples/DisplayTraits/Sample/AppDelegate.m new file mode 100644 index 0000000000..63928f1c38 --- /dev/null +++ b/examples/DisplayTraits/Sample/AppDelegate.m @@ -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 diff --git a/examples/DisplayTraits/Sample/CollectionViewController.h b/examples/DisplayTraits/Sample/CollectionViewController.h new file mode 100644 index 0000000000..613cf835e4 --- /dev/null +++ b/examples/DisplayTraits/Sample/CollectionViewController.h @@ -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 + +@interface CollectionViewController : ASViewController +@end diff --git a/examples/DisplayTraits/Sample/CollectionViewController.m b/examples/DisplayTraits/Sample/CollectionViewController.m new file mode 100644 index 0000000000..f4cba2ae37 --- /dev/null +++ b/examples/DisplayTraits/Sample/CollectionViewController.m @@ -0,0 +1,72 @@ +/* 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" + +@interface CollectionViewController () +@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 +{ + ASDisplayTraits displayTraits = self.collectionNode.environmentState.displayTraits; + + if (displayTraits.horizontalSizeClass == UIUserInterfaceSizeClassRegular) { + return ASSizeRangeMake(CGSizeMake(200, 120), CGSizeMake(200, 120)); + } + return ASSizeRangeMake(CGSizeMake(132, 180), CGSizeMake(132, 180)); +} + +@end diff --git a/examples/DisplayTraits/Sample/Info.plist b/examples/DisplayTraits/Sample/Info.plist new file mode 100644 index 0000000000..acc713cc71 --- /dev/null +++ b/examples/DisplayTraits/Sample/Info.plist @@ -0,0 +1,39 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + Launch Screen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + + diff --git a/examples/DisplayTraits/Sample/KittenNode.h b/examples/DisplayTraits/Sample/KittenNode.h new file mode 100644 index 0000000000..ae73a8900b --- /dev/null +++ b/examples/DisplayTraits/Sample/KittenNode.h @@ -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 + +@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 diff --git a/examples/DisplayTraits/Sample/KittenNode.m b/examples/DisplayTraits/Sample/KittenNode.m new file mode 100644 index 0000000000..d7d73c728c --- /dev/null +++ b/examples/DisplayTraits/Sample/KittenNode.m @@ -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" + +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 +{ + + ASDisplayTraits displayTraits = self.environmentState.displayTraits; + + ASStackLayoutSpec *stackSpec = [[ASStackLayoutSpec alloc] init]; + stackSpec.spacing = kInnerPadding; + stackSpec.children = @[_imageNode, _textNode]; + + if (displayTraits.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) { + return (ASDisplayTraits) { + .displayScale = traitCollection.displayScale, + .horizontalSizeClass = UIUserInterfaceSizeClassCompact, + .userInterfaceIdiom = traitCollection.userInterfaceIdiom, + .verticalSizeClass = UIUserInterfaceSizeClassCompact, + .forceTouchCapability = traitCollection.forceTouchCapability, + }; + }; + + [sourceViewController presentViewController:overrideVC animated:YES completion:nil]; + overrideVC.closeBlock = ^{ + [sourceViewController dismissViewControllerAnimated:YES completion:nil]; + }; +} + +@end diff --git a/examples/DisplayTraits/Sample/Launch Screen.storyboard b/examples/DisplayTraits/Sample/Launch Screen.storyboard new file mode 100644 index 0000000000..95c8ef474d --- /dev/null +++ b/examples/DisplayTraits/Sample/Launch Screen.storyboard @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/DisplayTraits/Sample/OverrideViewController.h b/examples/DisplayTraits/Sample/OverrideViewController.h new file mode 100644 index 0000000000..9d9e69d839 --- /dev/null +++ b/examples/DisplayTraits/Sample/OverrideViewController.h @@ -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 + +/* + * 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 +@property (nonatomic, copy) dispatch_block_t closeBlock; +@end diff --git a/examples/DisplayTraits/Sample/OverrideViewController.m b/examples/DisplayTraits/Sample/OverrideViewController.m new file mode 100644 index 0000000000..7bcb3b7276 --- /dev/null +++ b/examples/DisplayTraits/Sample/OverrideViewController.m @@ -0,0 +1,95 @@ +/* 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" +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; + ASDisplayTraits displayTraits = self.environmentState.displayTraits; + if (displayTraits.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 diff --git a/examples/DisplayTraits/Sample/TableViewController.h b/examples/DisplayTraits/Sample/TableViewController.h new file mode 100644 index 0000000000..364dde8597 --- /dev/null +++ b/examples/DisplayTraits/Sample/TableViewController.h @@ -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 + +@interface TableViewController : ASViewController + +@end diff --git a/examples/DisplayTraits/Sample/TableViewController.m b/examples/DisplayTraits/Sample/TableViewController.m new file mode 100644 index 0000000000..bd897a7c75 --- /dev/null +++ b/examples/DisplayTraits/Sample/TableViewController.m @@ -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 () +@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 diff --git a/examples/DisplayTraits/Sample/ViewController.h b/examples/DisplayTraits/Sample/ViewController.h new file mode 100644 index 0000000000..aa1d583729 --- /dev/null +++ b/examples/DisplayTraits/Sample/ViewController.h @@ -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 + +@interface ViewController : ASViewController + +@end diff --git a/examples/DisplayTraits/Sample/ViewController.m b/examples/DisplayTraits/Sample/ViewController.m new file mode 100644 index 0000000000..42e9cb9a4a --- /dev/null +++ b/examples/DisplayTraits/Sample/ViewController.m @@ -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 +#import + +@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 diff --git a/examples/DisplayTraits/Sample/main.m b/examples/DisplayTraits/Sample/main.m new file mode 100644 index 0000000000..ae9488711c --- /dev/null +++ b/examples/DisplayTraits/Sample/main.m @@ -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 + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +}