diff --git a/.github_changelog_generator b/.github_changelog_generator new file mode 100644 index 0000000000..a5410c8d8e --- /dev/null +++ b/.github_changelog_generator @@ -0,0 +1,3 @@ +issues=false +since-tag=2.3 +future-release=2.8 diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 40cc8eeea7..d266687e29 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -7,30 +7,30 @@ objects = { /* Begin PBXBuildFile section */ - 044284FD1BAA365100D16268 /* UICollectionViewLayout+ASConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E0E1B371875007741D0 /* UICollectionViewLayout+ASConvenience.m */; }; + 044284FD1BAA365100D16268 /* UICollectionViewLayout+ASConvenience.mm in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E0E1B371875007741D0 /* UICollectionViewLayout+ASConvenience.mm */; }; 044284FF1BAA3BD600D16268 /* UICollectionViewLayout+ASConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = 205F0E0D1B371875007741D0 /* UICollectionViewLayout+ASConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; 044285081BAA63FE00D16268 /* ASBatchFetching.h in Headers */ = {isa = PBXBuildFile; fileRef = 044285051BAA63FE00D16268 /* ASBatchFetching.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0442850A1BAA63FE00D16268 /* ASBatchFetching.m in Sources */ = {isa = PBXBuildFile; fileRef = 044285061BAA63FE00D16268 /* ASBatchFetching.m */; }; + 0442850A1BAA63FE00D16268 /* ASBatchFetching.mm in Sources */ = {isa = PBXBuildFile; fileRef = 044285061BAA63FE00D16268 /* ASBatchFetching.mm */; }; 0442850E1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0442850B1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 044285101BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 0442850C1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.m */; }; - 052EE0661A159FEF002C6279 /* ASMultiplexImageNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 052EE0651A159FEF002C6279 /* ASMultiplexImageNodeTests.m */; }; + 044285101BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0442850C1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.mm */; }; + 052EE0661A159FEF002C6279 /* ASMultiplexImageNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 052EE0651A159FEF002C6279 /* ASMultiplexImageNodeTests.mm */; }; 052EE06B1A15A0D8002C6279 /* TestResources in Resources */ = {isa = PBXBuildFile; fileRef = 052EE06A1A15A0D8002C6279 /* TestResources */; }; - 056D21551ABCEF50001107EF /* ASImageNodeSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 056D21541ABCEF50001107EF /* ASImageNodeSnapshotTests.m */; }; - 057D02C41AC0A66700C7AC3C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 057D02C31AC0A66700C7AC3C /* main.m */; }; - 057D02C71AC0A66700C7AC3C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 057D02C61AC0A66700C7AC3C /* AppDelegate.m */; }; + 056D21551ABCEF50001107EF /* ASImageNodeSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 056D21541ABCEF50001107EF /* ASImageNodeSnapshotTests.mm */; }; + 057D02C41AC0A66700C7AC3C /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 057D02C31AC0A66700C7AC3C /* main.mm */; }; + 057D02C71AC0A66700C7AC3C /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 057D02C61AC0A66700C7AC3C /* AppDelegate.mm */; }; 058D09BE195D04C000B7D73C /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09BD195D04C000B7D73C /* XCTest.framework */; }; 058D09BF195D04C000B7D73C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AF195D04C000B7D73C /* Foundation.framework */; }; 058D09C1195D04C000B7D73C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09C0195D04C000B7D73C /* UIKit.framework */; }; 058D09CA195D04C000B7D73C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 058D09C8195D04C000B7D73C /* InfoPlist.strings */; }; - 058D0A38195D057000B7D73C /* ASDisplayLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A2D195D057000B7D73C /* ASDisplayLayerTests.m */; }; - 058D0A39195D057000B7D73C /* ASDisplayNodeAppearanceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A2E195D057000B7D73C /* ASDisplayNodeAppearanceTests.m */; }; + 058D0A38195D057000B7D73C /* ASDisplayLayerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A2D195D057000B7D73C /* ASDisplayLayerTests.mm */; }; + 058D0A39195D057000B7D73C /* ASDisplayNodeAppearanceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A2E195D057000B7D73C /* ASDisplayNodeAppearanceTests.mm */; }; 058D0A3A195D057000B7D73C /* ASDisplayNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A2F195D057000B7D73C /* ASDisplayNodeTests.mm */; }; - 058D0A3B195D057000B7D73C /* ASDisplayNodeTestsHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A31195D057000B7D73C /* ASDisplayNodeTestsHelper.m */; }; - 058D0A3C195D057000B7D73C /* ASMutableAttributedStringBuilderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A32195D057000B7D73C /* ASMutableAttributedStringBuilderTests.m */; }; - 058D0A3D195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A33195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.m */; }; - 058D0A40195D057000B7D73C /* ASTextNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A36195D057000B7D73C /* ASTextNodeTests.m */; }; + 058D0A3B195D057000B7D73C /* ASDisplayNodeTestsHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A31195D057000B7D73C /* ASDisplayNodeTestsHelper.mm */; }; + 058D0A3C195D057000B7D73C /* ASMutableAttributedStringBuilderTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A32195D057000B7D73C /* ASMutableAttributedStringBuilderTests.mm */; }; + 058D0A3D195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A33195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.mm */; }; + 058D0A40195D057000B7D73C /* ASTextNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A36195D057000B7D73C /* ASTextNodeTests.mm */; }; 058D0A41195D057000B7D73C /* ASTextNodeWordKernerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A37195D057000B7D73C /* ASTextNodeWordKernerTests.mm */; }; - 05EA6FE71AC0966E00E35788 /* ASSnapshotTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 05EA6FE61AC0966E00E35788 /* ASSnapshotTestCase.m */; }; + 05EA6FE71AC0966E00E35788 /* ASSnapshotTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 05EA6FE61AC0966E00E35788 /* ASSnapshotTestCase.mm */; }; 0FAFDF7520EC1C90003A51C0 /* ASLayout+IGListKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FAFDF7320EC1C8F003A51C0 /* ASLayout+IGListKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0FAFDF7620EC1C90003A51C0 /* ASLayout+IGListKit.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FAFDF7420EC1C90003A51C0 /* ASLayout+IGListKit.mm */; }; 18C2ED7F1B9B7DE800F627B3 /* ASCollectionNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 18C2ED7C1B9B7DE800F627B3 /* ASCollectionNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -38,8 +38,8 @@ 1A6C000D1FAB4E2100D05926 /* ASCornerLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A6C000B1FAB4E2000D05926 /* ASCornerLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1A6C000E1FAB4E2100D05926 /* ASCornerLayoutSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A6C000C1FAB4E2100D05926 /* ASCornerLayoutSpec.mm */; }; 1A6C00111FAB4EDD00D05926 /* ASCornerLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A6C000F1FAB4ED400D05926 /* ASCornerLayoutSpecSnapshotTests.mm */; }; - 242995D31B29743C00090100 /* ASBasicImageDownloaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 242995D21B29743C00090100 /* ASBasicImageDownloaderTests.m */; }; - 2538B6F31BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */; }; + 242995D31B29743C00090100 /* ASBasicImageDownloaderTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 242995D21B29743C00090100 /* ASBasicImageDownloaderTests.mm */; }; + 2538B6F31BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.mm */; }; 254C6B521BF8FE6D003EC431 /* ASTextKitTruncationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 254C6B511BF8FE6D003EC431 /* ASTextKitTruncationTests.mm */; }; 254C6B541BF8FF2A003EC431 /* ASTextKitTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 254C6B531BF8FF2A003EC431 /* ASTextKitTests.mm */; }; 254C6B731BF94DF4003EC431 /* ASTextKitCoreTextAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -56,28 +56,28 @@ 254C6B7E1BF94DF4003EC431 /* ASTextKitTailTruncater.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754A11BEE44CD00737CA5 /* ASTextKitTailTruncater.h */; settings = {ATTRIBUTES = (Private, ); }; }; 254C6B7F1BF94DF4003EC431 /* ASTextKitTruncating.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754A31BEE44CD00737CA5 /* ASTextKitTruncating.h */; settings = {ATTRIBUTES = (Private, ); }; }; 254C6B821BF94F8A003EC431 /* ASTextKitComponents.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754B71BEE458D00737CA5 /* ASTextKitComponents.mm */; }; - 254C6B831BF94F8A003EC431 /* ASTextKitCoreTextAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m */; }; - 254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */; }; + 254C6B831BF94F8A003EC431 /* ASTextKitCoreTextAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.mm */; }; + 254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.mm */; }; 254C6B851BF94F8A003EC431 /* ASTextKitAttributes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754941BEE44CD00737CA5 /* ASTextKitAttributes.mm */; }; 254C6B861BF94F8A003EC431 /* ASTextKitContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754971BEE44CD00737CA5 /* ASTextKitContext.mm */; }; - 254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754991BEE44CD00737CA5 /* ASTextKitEntityAttribute.m */; }; + 254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754991BEE44CD00737CA5 /* ASTextKitEntityAttribute.mm */; }; 254C6B881BF94F8A003EC431 /* ASTextKitRenderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2577549A1BEE44CD00737CA5 /* ASTextKitRenderer.mm */; }; 254C6B891BF94F8A003EC431 /* ASTextKitRenderer+Positioning.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2577549C1BEE44CD00737CA5 /* ASTextKitRenderer+Positioning.mm */; }; 254C6B8A1BF94F8A003EC431 /* ASTextKitRenderer+TextChecking.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2577549E1BEE44CD00737CA5 /* ASTextKitRenderer+TextChecking.mm */; }; 254C6B8B1BF94F8A003EC431 /* ASTextKitShadower.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754A01BEE44CD00737CA5 /* ASTextKitShadower.mm */; }; 254C6B8C1BF94F8A003EC431 /* ASTextKitTailTruncater.mm in Sources */ = {isa = PBXBuildFile; fileRef = 257754A21BEE44CD00737CA5 /* ASTextKitTailTruncater.mm */; }; 25E327571C16819500A2170C /* ASPagerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 25E327541C16819500A2170C /* ASPagerNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 25E327591C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; }; + 25E327591C16819500A2170C /* ASPagerNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.mm */; }; 2767E9411BB19BD600EA9B77 /* ASViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2911485C1A77147A005D0878 /* ASControlNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2911485B1A77147A005D0878 /* ASControlNodeTests.m */; }; - 296A0A351A951ABF005ACEAA /* ASBatchFetchingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 296A0A341A951ABF005ACEAA /* ASBatchFetchingTests.m */; }; - 29CDC2E21AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CDC2E11AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.m */; }; + 2911485C1A77147A005D0878 /* ASControlNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2911485B1A77147A005D0878 /* ASControlNodeTests.mm */; }; + 296A0A351A951ABF005ACEAA /* ASBatchFetchingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 296A0A341A951ABF005ACEAA /* ASBatchFetchingTests.mm */; }; + 29CDC2E21AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29CDC2E11AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.mm */; }; 2C107F5B1BA9F54500F13DE5 /* AsyncDisplayKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 34566CB31BC1213700715E6B /* ASPhotosFrameworkImageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */; }; + 34566CB31BC1213700715E6B /* ASPhotosFrameworkImageRequest.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.mm */; }; 34EFC75B1B701BAF00AD841F /* ASDimension.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED071B17843500DA7C62 /* ASDimension.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34EFC75C1B701BD200AD841F /* ASDimension.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED081B17843500DA7C62 /* ASDimension.mm */; }; 34EFC75D1B701BE900AD841F /* ASInternalHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 34EFC75E1B701BF000AD841F /* ASInternalHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.m */; }; + 34EFC75E1B701BF000AD841F /* ASInternalHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.mm */; }; 34EFC75F1B701C8600AD841F /* ASInsetLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED091B17843500DA7C62 /* ASInsetLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34EFC7601B701C8B00AD841F /* ASInsetLayoutSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED0A1B17843500DA7C62 /* ASInsetLayoutSpec.mm */; }; 34EFC7611B701C9C00AD841F /* ASBackgroundLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED011B17843500DA7C62 /* ASBackgroundLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -99,48 +99,46 @@ 34EFC7731B701D0700AD841F /* ASAbsoluteLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED181B17843500DA7C62 /* ASAbsoluteLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34EFC7741B701D0A00AD841F /* ASAbsoluteLayoutSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED191B17843500DA7C62 /* ASAbsoluteLayoutSpec.mm */; }; 3917EBD41E9C2FC400D04A01 /* _ASCollectionReusableView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3917EBD21E9C2FC400D04A01 /* _ASCollectionReusableView.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 3917EBD51E9C2FC400D04A01 /* _ASCollectionReusableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3917EBD31E9C2FC400D04A01 /* _ASCollectionReusableView.m */; }; + 3917EBD51E9C2FC400D04A01 /* _ASCollectionReusableView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3917EBD31E9C2FC400D04A01 /* _ASCollectionReusableView.mm */; }; 3C9C128519E616EF00E942A0 /* ASTableViewTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C9C128419E616EF00E942A0 /* ASTableViewTests.mm */; }; - 4496D0731FA9EA6B001CC8D5 /* ASTraitCollectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4496D0721FA9EA6B001CC8D5 /* ASTraitCollectionTests.m */; }; - 4E9127691F64157600499623 /* ASRunLoopQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E9127681F64157600499623 /* ASRunLoopQueueTests.m */; }; - 509E68601B3AED8E009B9150 /* ASScrollDirection.m in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E111B371BD7007741D0 /* ASScrollDirection.m */; }; + 4E9127691F64157600499623 /* ASRunLoopQueueTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4E9127681F64157600499623 /* ASRunLoopQueueTests.mm */; }; + 509E68601B3AED8E009B9150 /* ASScrollDirection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E111B371BD7007741D0 /* ASScrollDirection.mm */; }; 509E68611B3AEDA0009B9150 /* ASAbstractLayoutController.h in Headers */ = {isa = PBXBuildFile; fileRef = 205F0E171B37339C007741D0 /* ASAbstractLayoutController.h */; }; 509E68621B3AEDA5009B9150 /* ASAbstractLayoutController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E181B37339C007741D0 /* ASAbstractLayoutController.mm */; }; 509E68631B3AEDB4009B9150 /* ASCollectionViewLayoutController.h in Headers */ = {isa = PBXBuildFile; fileRef = 205F0E1B1B373A2C007741D0 /* ASCollectionViewLayoutController.h */; }; - 509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.m */; }; + 509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.mm */; }; 509E68651B3AEDC5009B9150 /* CoreGraphics+ASConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = 205F0E1F1B376416007741D0 /* CoreGraphics+ASConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 509E68661B3AEDD7009B9150 /* CoreGraphics+ASConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E201B376416007741D0 /* CoreGraphics+ASConvenience.m */; }; 636EA1A41C7FF4EC00EE152F /* NSArray+Diffing.mm in Sources */ = {isa = PBXBuildFile; fileRef = DBC452DA1C5BF64600B16017 /* NSArray+Diffing.mm */; }; - 636EA1A51C7FF4EF00EE152F /* ASDefaultPlayButton.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */; }; + 636EA1A51C7FF4EF00EE152F /* ASDefaultPlayButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.mm */; }; 680346941CE4052A0009FEB4 /* ASNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85DC1CE29AB700EDD713 /* ASNavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 68355B341CB579B9001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */; }; - 68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */; }; - 68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */; }; + 68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.mm */; }; + 68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.mm */; }; 68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */; settings = {ATTRIBUTES = (Public, ); }; }; 683F563720E409D700CEB7A3 /* ASDisplayNode+InterfaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = 683F563620E409D600CEB7A3 /* ASDisplayNode+InterfaceState.h */; settings = {ATTRIBUTES = (Public, ); }; }; 68AF37DB1CBEF4D80077BF76 /* ASImageNode+AnimatedImagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 68B0277B1C1A79D60041016B /* ASDisplayNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; 68B8A4E21CBDB958007E4543 /* ASWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 68B8A4E41CBDB958007E4543 /* ASWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B8A4E01CBDB958007E4543 /* ASWeakProxy.m */; }; + 68B8A4E41CBDB958007E4543 /* ASWeakProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68B8A4E01CBDB958007E4543 /* ASWeakProxy.mm */; }; 68C215581DE10D330019C4BC /* ASCollectionViewLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 68C215561DE10D330019C4BC /* ASCollectionViewLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 68C2155A1DE10D330019C4BC /* ASCollectionViewLayoutInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C215571DE10D330019C4BC /* ASCollectionViewLayoutInspector.m */; }; + 68C2155A1DE10D330019C4BC /* ASCollectionViewLayoutInspector.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68C215571DE10D330019C4BC /* ASCollectionViewLayoutInspector.mm */; }; 68EE0DBE1C1B4ED300BA1B99 /* ASMainSerialQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */; settings = {ATTRIBUTES = (Private, ); }; }; 68EE0DC01C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */; }; 68FC85E31CE29B7E00EDD713 /* ASTabBarController.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85E01CE29B7E00EDD713 /* ASTabBarController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 68FC85E51CE29B7E00EDD713 /* ASTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */; }; - 68FC85E61CE29B9400EDD713 /* ASNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85DD1CE29AB700EDD713 /* ASNavigationController.m */; }; + 68FC85E51CE29B7E00EDD713 /* ASTabBarController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E11CE29B7E00EDD713 /* ASTabBarController.mm */; }; + 68FC85E61CE29B9400EDD713 /* ASNavigationController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85DD1CE29AB700EDD713 /* ASNavigationController.mm */; }; 68FC85EA1CE29C7D00EDD713 /* ASVisibilityProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 68FC85EC1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */; }; + 68FC85EC1CE29C7D00EDD713 /* ASVisibilityProtocols.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.mm */; }; 6900C5F41E8072DA00BCD75C /* ASImageNode+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6900C5F31E8072DA00BCD75C /* ASImageNode+Private.h */; }; 6907C2581DC4ECFE00374C66 /* ASObjectDescriptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 6907C2561DC4ECFE00374C66 /* ASObjectDescriptionHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6907C25A1DC4ECFE00374C66 /* ASObjectDescriptionHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 6907C2571DC4ECFE00374C66 /* ASObjectDescriptionHelpers.m */; }; + 6907C25A1DC4ECFE00374C66 /* ASObjectDescriptionHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6907C2571DC4ECFE00374C66 /* ASObjectDescriptionHelpers.mm */; }; 690BC8C120F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 690BC8BF20F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 690BC8C220F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 690BC8C020F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.m */; }; + 690BC8C220F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 690BC8C020F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.mm */; }; 690C35621E055C5D00069B91 /* ASDimensionInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 690C35601E055C5D00069B91 /* ASDimensionInternal.mm */; }; 690C35641E055C7B00069B91 /* ASDimensionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 690C35631E055C7B00069B91 /* ASDimensionInternal.h */; settings = {ATTRIBUTES = (Public, ); }; }; 690ED58E1E36BCA6000627C0 /* ASLayoutElementStylePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 690ED58D1E36BCA6000627C0 /* ASLayoutElementStylePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 690ED5981E36D118000627C0 /* ASControlNode+tvOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 690ED5931E36D118000627C0 /* ASControlNode+tvOS.m */; }; - 690ED59B1E36D118000627C0 /* ASImageNode+tvOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 690ED5951E36D118000627C0 /* ASImageNode+tvOS.m */; }; + 690ED5981E36D118000627C0 /* ASControlNode+tvOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 690ED5931E36D118000627C0 /* ASControlNode+tvOS.mm */; }; + 690ED59B1E36D118000627C0 /* ASImageNode+tvOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 690ED5951E36D118000627C0 /* ASImageNode+tvOS.mm */; }; 692510141E74FB44003F2DD0 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 692510131E74FB44003F2DD0 /* Default-568h@2x.png */; }; 692BE8D71E36B65B00C86D87 /* ASLayoutSpecPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 692BE8D61E36B65B00C86D87 /* ASLayoutSpecPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 693A1DCA1ECC944E00D0C9D2 /* IGListAdapter+AsyncDisplayKit.h in Headers */ = {isa = PBXBuildFile; fileRef = CCE04B201E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -155,7 +153,7 @@ 696FCB311D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 696FCB301D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm */; }; 6977965F1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.h in Headers */ = {isa = PBXBuildFile; fileRef = 6977965D1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.h */; settings = {ATTRIBUTES = (Private, ); }; }; 697796611D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6977965E1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm */; }; - 697B315A1CFE4B410049936F /* ASEditableTextNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 697B31591CFE4B410049936F /* ASEditableTextNodeTests.m */; }; + 697B315A1CFE4B410049936F /* ASEditableTextNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 697B31591CFE4B410049936F /* ASEditableTextNodeTests.mm */; }; 698371DB1E4379CD00437585 /* ASNodeController+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 698371D91E4379CD00437585 /* ASNodeController+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; 698371DC1E4379CD00437585 /* ASNodeController+Beta.mm in Sources */ = {isa = PBXBuildFile; fileRef = 698371DA1E4379CD00437585 /* ASNodeController+Beta.mm */; }; 698C8B621CAB49FC0052DC3F /* ASLayoutElementExtensibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 698C8B601CAB49FC0052DC3F /* ASLayoutElementExtensibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -167,21 +165,21 @@ 69CB62AE1CB8165900024920 /* _ASDisplayViewAccessiblity.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69CB62AA1CB8165900024920 /* _ASDisplayViewAccessiblity.mm */; }; 69E0E8A71D356C9400627613 /* ASEqualityHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 1950C4481A3BB5C1005C8279 /* ASEqualityHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; }; 69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 69FEE53D1D95A9AF0086F066 /* ASLayoutElementStyleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.m */; }; + 69FEE53D1D95A9AF0086F066 /* ASLayoutElementStyleTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.mm */; }; 7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */ = {isa = PBXBuildFile; fileRef = AEEC47DF1C20C2DD00EC1693 /* ASVideoNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 764D83D51C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h in Headers */ = {isa = PBXBuildFile; fileRef = 764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 767E7F8E1C90191D0066C000 /* AsyncDisplayKit+Debug.m in Sources */ = {isa = PBXBuildFile; fileRef = 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */; }; + 767E7F8E1C90191D0066C000 /* AsyncDisplayKit+Debug.mm in Sources */ = {isa = PBXBuildFile; fileRef = 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.mm */; }; 7AB338661C55B3420055FDE8 /* ASRelativeLayoutSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A06A7381C35F08800FE8DAA /* ASRelativeLayoutSpec.mm */; }; 7AB338671C55B3460055FDE8 /* ASRelativeLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A06A7391C35F08800FE8DAA /* ASRelativeLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7AB338691C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7AB338681C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm */; }; 8021EC1D1D2B00B100799119 /* UIImage+ASConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = 8021EC1A1D2B00B100799119 /* UIImage+ASConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8021EC1F1D2B00B100799119 /* UIImage+ASConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = 8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.m */; }; - 81E95C141D62639600336598 /* ASTextNodeSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 81E95C131D62639600336598 /* ASTextNodeSnapshotTests.m */; }; - 83A7D95B1D44547700BF333E /* ASWeakMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A7D9591D44542100BF333E /* ASWeakMap.m */; }; + 8021EC1F1D2B00B100799119 /* UIImage+ASConvenience.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.mm */; }; + 81E95C141D62639600336598 /* ASTextNodeSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 81E95C131D62639600336598 /* ASTextNodeSnapshotTests.mm */; }; + 83A7D95B1D44547700BF333E /* ASWeakMap.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83A7D9591D44542100BF333E /* ASWeakMap.mm */; }; 83A7D95C1D44548100BF333E /* ASWeakMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A7D9581D44542100BF333E /* ASWeakMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 83A7D95E1D446A6E00BF333E /* ASWeakMapTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A7D95D1D446A6E00BF333E /* ASWeakMapTests.m */; }; + 83A7D95E1D446A6E00BF333E /* ASWeakMapTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83A7D95D1D446A6E00BF333E /* ASWeakMapTests.mm */; }; 8BBBAB8C1CEBAF1700107FC6 /* ASDefaultPlaybackButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B0768B11CE752EC002E1453 /* ASDefaultPlaybackButton.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 8BBBAB8D1CEBAF1E00107FC6 /* ASDefaultPlaybackButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.m */; }; + 8BBBAB8D1CEBAF1E00107FC6 /* ASDefaultPlaybackButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.mm */; }; 8BDA5FC71CDBDF91007D13B2 /* ASVideoPlayerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BDA5FC31CDBDDE1007D13B2 /* ASVideoPlayerNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8BDA5FC81CDBDF95007D13B2 /* ASVideoPlayerNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8BDA5FC41CDBDDE1007D13B2 /* ASVideoPlayerNode.mm */; }; 9019FBBF1ED8061D00C45F72 /* ASYogaUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 9019FBBB1ED8061D00C45F72 /* ASYogaUtilities.h */; }; @@ -193,10 +191,10 @@ 92DD2FE71BF4D0850074C9DD /* ASMapNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 92DD2FE21BF4B97E0074C9DD /* ASMapNode.mm */; }; 92DD2FE81BF4D0A80074C9DD /* ASMapNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 92DD2FE11BF4B97E0074C9DD /* ASMapNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C49C3701B853961000B0DD5 /* ASStackLayoutElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C49C36E1B853957000B0DD5 /* ASStackLayoutElement.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9C55866B1BD54A1900B50E3A /* ASAsciiArtBoxCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.m */; }; + 9C55866B1BD54A1900B50E3A /* ASAsciiArtBoxCreator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.mm */; }; 9C55866C1BD54A3000B50E3A /* ASAsciiArtBoxCreator.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5586671BD549CB00B50E3A /* ASAsciiArtBoxCreator.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C6BB3B31B8CC9C200F13F52 /* ASAbsoluteLayoutElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6BB3B01B8CC9C200F13F52 /* ASAbsoluteLayoutElement.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9C70F2051CDA4F06007D6C76 /* ASTraitCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */; }; + 9C70F2051CDA4F06007D6C76 /* ASTraitCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.mm */; }; 9C70F2061CDA4F0C007D6C76 /* ASTraitCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C70F2091CDABA36007D6C76 /* ASViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */; }; 9C70F20A1CDBE949007D6C76 /* ASTableNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */; }; @@ -205,34 +203,34 @@ 9C70F20F1CDBE9FF007D6C76 /* ASLayoutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */; settings = {ATTRIBUTES = (Private, ); }; }; 9C8898BC1C738BA800D6B02E /* ASTextKitFontSizeAdjuster.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C8898BA1C738B9800D6B02E /* ASTextKitFontSizeAdjuster.mm */; }; 9C8898BD1C738BB800D6B02E /* ASTextKitFontSizeAdjuster.h in Headers */ = {isa = PBXBuildFile; fileRef = A32FEDD31C501B6A004F642A /* ASTextKitFontSizeAdjuster.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 9CC606651D24DF9E006581A0 /* NSIndexSet+ASHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.m */; }; + 9CC606651D24DF9E006581A0 /* NSIndexSet+ASHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.mm */; }; 9CDC18CD1B910E12004965E2 /* ASLayoutElementPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDC18CB1B910E12004965E2 /* ASLayoutElementPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9F06E5CD1B4CAF4200F015D8 /* ASCollectionViewTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.mm */; }; - 9F98C0261DBE29E000476D92 /* ASControlTargetAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F98C0241DBDF2A300476D92 /* ASControlTargetAction.m */; }; + 9F98C0261DBE29E000476D92 /* ASControlTargetAction.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9F98C0241DBDF2A300476D92 /* ASControlTargetAction.mm */; }; 9F98C0271DBE29FC00476D92 /* ASControlTargetAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F98C0231DBDF2A300476D92 /* ASControlTargetAction.h */; settings = {ATTRIBUTES = (Private, ); }; }; A2763D7A1CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; A37320101C571B740011FC94 /* ASTextNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = A373200E1C571B050011FC94 /* ASTextNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AC026B581BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AC026B571BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.m */; }; + AC026B581BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC026B571BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.mm */; }; AC026B701BD57DBF00BBC17E /* _ASHierarchyChangeSet.h in Headers */ = {isa = PBXBuildFile; fileRef = AC026B6D1BD57DBF00BBC17E /* _ASHierarchyChangeSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; AC026B721BD57DBF00BBC17E /* _ASHierarchyChangeSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC026B6E1BD57DBF00BBC17E /* _ASHierarchyChangeSet.mm */; }; AC47D9421B3B891B00AAEE9D /* ASCellNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC6456071B0A335000CF11B8 /* ASCellNode.mm */; }; AC6145411D8AFAE8003D62A2 /* ASSection.h in Headers */ = {isa = PBXBuildFile; fileRef = AC6145401D8AFAE8003D62A2 /* ASSection.h */; settings = {ATTRIBUTES = (Private, ); }; }; - AC6145441D8AFD4F003D62A2 /* ASSection.m in Sources */ = {isa = PBXBuildFile; fileRef = AC6145421D8AFD4F003D62A2 /* ASSection.m */; }; + AC6145441D8AFD4F003D62A2 /* ASSection.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC6145421D8AFD4F003D62A2 /* ASSection.mm */; }; AC7A2C181BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; ACE87A2C1D73696800D7FF06 /* ASSectionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = ACE87A2B1D73696800D7FF06 /* ASSectionContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; ACF6ED5C1B178DC700DA7C62 /* ASCenterLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED531B178DC700DA7C62 /* ASCenterLayoutSpecSnapshotTests.mm */; }; ACF6ED5D1B178DC700DA7C62 /* ASDimensionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED541B178DC700DA7C62 /* ASDimensionTests.mm */; }; ACF6ED5E1B178DC700DA7C62 /* ASInsetLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED551B178DC700DA7C62 /* ASInsetLayoutSpecSnapshotTests.mm */; }; - ACF6ED601B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED581B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.m */; }; + ACF6ED601B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED581B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.mm */; }; ACF6ED611B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED591B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm */; }; ACF6ED621B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED5A1B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm */; }; ACF6ED631B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED5B1B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm */; }; AE440175210FB7CF00B36DA2 /* ASTextKitFontSizeAdjusterTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE440174210FB7CF00B36DA2 /* ASTextKitFontSizeAdjusterTests.mm */; }; - AE6987C11DD04E1000B9E458 /* ASPagerNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AE6987C01DD04E1000B9E458 /* ASPagerNodeTests.m */; }; - AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */; }; + AE6987C11DD04E1000B9E458 /* ASPagerNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE6987C01DD04E1000B9E458 /* ASPagerNodeTests.mm */; }; + AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.mm */; }; B13CA0F81C519EBA00E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0F61C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; B13CA1011C52004900E031AB /* ASCollectionNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B30BF6541C59D889004FCD53 /* ASLayoutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */; }; + B30BF6541C59D889004FCD53 /* ASLayoutManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = B30BF6511C5964B0004FCD53 /* ASLayoutManager.mm */; }; B35061F31B010EFD0018CF92 /* ASCellNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 055F1A3A19ABD43F004DAFF1 /* ASCellNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35061F51B010EFD0018CF92 /* ASCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35061F61B010EFD0018CF92 /* ASCollectionView.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A501A1139C100143C57 /* ASCollectionView.mm */; }; @@ -267,31 +265,31 @@ B35062131B010EFD0018CF92 /* ASBasicImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 054963471A1EA066000F8E56 /* ASBasicImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 054963481A1EA066000F8E56 /* ASBasicImageDownloader.mm */; }; B35062151B010EFD0018CF92 /* ASBatchContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 299DA1A71A828D2900162D41 /* ASBatchContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B35062161B010EFD0018CF92 /* ASBatchContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 299DA1A81A828D2900162D41 /* ASBatchContext.m */; }; + B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 299DA1A81A828D2900162D41 /* ASBatchContext.mm */; }; B35062171B010EFD0018CF92 /* ASDataController.h in Headers */ = {isa = PBXBuildFile; fileRef = 464052191A3F83C40061C0BA /* ASDataController.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062181B010EFD0018CF92 /* ASDataController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4640521A1A3F83C40061C0BA /* ASDataController.mm */; }; B350621B1B010EFD0018CF92 /* ASTableLayoutController.h in Headers */ = {isa = PBXBuildFile; fileRef = 4640521B1A3F83C40061C0BA /* ASTableLayoutController.h */; settings = {ATTRIBUTES = (Private, ); }; }; - B350621C1B010EFD0018CF92 /* ASTableLayoutController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4640521C1A3F83C40061C0BA /* ASTableLayoutController.m */; }; + B350621C1B010EFD0018CF92 /* ASTableLayoutController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4640521C1A3F83C40061C0BA /* ASTableLayoutController.mm */; }; B350621D1B010EFD0018CF92 /* ASHighlightOverlayLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E7195D050800B7D73C /* ASHighlightOverlayLayer.mm */; }; B350621F1B010EFD0018CF92 /* ASImageProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 05F20AA31A15733C00DCA68A /* ASImageProtocols.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062201B010EFD0018CF92 /* ASLayoutController.h in Headers */ = {isa = PBXBuildFile; fileRef = 4640521D1A3F83C40061C0BA /* ASLayoutController.h */; }; B35062211B010EFD0018CF92 /* ASLayoutRangeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C59991A956527007E5DD6 /* ASLayoutRangeType.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062241B010EFD0018CF92 /* ASMutableAttributedStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D09E8195D050800B7D73C /* ASMutableAttributedStringBuilder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B35062251B010EFD0018CF92 /* ASMutableAttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.m */; }; + B35062251B010EFD0018CF92 /* ASMutableAttributedStringBuilder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.mm */; }; B35062261B010EFD0018CF92 /* ASRangeController.h in Headers */ = {isa = PBXBuildFile; fileRef = 055F1A3619ABD413004DAFF1 /* ASRangeController.h */; }; B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 055F1A3719ABD413004DAFF1 /* ASRangeController.mm */; }; B350622D1B010EFD0018CF92 /* ASScrollDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 296A0A311A951715005ACEAA /* ASScrollDirection.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062391B010EFD0018CF92 /* ASThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A12195D050800B7D73C /* ASThread.h */; settings = {ATTRIBUTES = (Public, ); }; }; B350623A1B010EFD0018CF92 /* NSMutableAttributedString+TextKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D09F5195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B350623B1B010EFD0018CF92 /* NSMutableAttributedString+TextKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09F6195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m */; }; + B350623B1B010EFD0018CF92 /* NSMutableAttributedString+TextKitAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09F6195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.mm */; }; B350623C1B010EFD0018CF92 /* _ASAsyncTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D09F8195D050800B7D73C /* _ASAsyncTransaction.h */; settings = {ATTRIBUTES = (Public, ); }; }; B350623D1B010EFD0018CF92 /* _ASAsyncTransaction.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09F9195D050800B7D73C /* _ASAsyncTransaction.mm */; }; B350623E1B010EFD0018CF92 /* _ASAsyncTransactionContainer+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D09FA195D050800B7D73C /* _ASAsyncTransactionContainer+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; B350623F1B010EFD0018CF92 /* _ASAsyncTransactionContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D09FB195D050800B7D73C /* _ASAsyncTransactionContainer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B35062401B010EFD0018CF92 /* _ASAsyncTransactionContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09FC195D050800B7D73C /* _ASAsyncTransactionContainer.m */; }; + B35062401B010EFD0018CF92 /* _ASAsyncTransactionContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09FC195D050800B7D73C /* _ASAsyncTransactionContainer.mm */; }; B35062411B010EFD0018CF92 /* _ASAsyncTransactionGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D09FD195D050800B7D73C /* _ASAsyncTransactionGroup.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B35062421B010EFD0018CF92 /* _ASAsyncTransactionGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09FE195D050800B7D73C /* _ASAsyncTransactionGroup.m */; }; + B35062421B010EFD0018CF92 /* _ASAsyncTransactionGroup.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D09FE195D050800B7D73C /* _ASAsyncTransactionGroup.mm */; }; B35062431B010EFD0018CF92 /* UIView+ASConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D09FF195D050800B7D73C /* UIView+ASConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062461B010EFD0018CF92 /* ASBasicImageDownloaderInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2967F9E11AB0A4CF0072E4AB /* ASBasicImageDownloaderInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; B35062491B010EFD0018CF92 /* _ASCoreAnimationExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A03195D050800B7D73C /* _ASCoreAnimationExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -305,165 +303,176 @@ B35062511B010EFD0018CF92 /* ASDisplayNode+UIViewBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A0B195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm */; }; B35062521B010EFD0018CF92 /* ASDisplayNodeInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; B35062531B010EFD0018CF92 /* ASImageNode+CGExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A0D195D050800B7D73C /* ASImageNode+CGExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; - B35062541B010EFD0018CF92 /* ASImageNode+CGExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.m */; }; + B35062541B010EFD0018CF92 /* ASImageNode+CGExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = 058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.mm */; }; B35062571B010F070018CF92 /* ASAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A43195D058D00B7D73C /* ASAssert.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062581B010F070018CF92 /* ASAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 0516FA3A1A15563400B4EBED /* ASAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062591B010F070018CF92 /* ASBaseDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A44195D058D00B7D73C /* ASBaseDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; B350625C1B010F070018CF92 /* ASLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 0516FA3B1A15563400B4EBED /* ASLog.h */; settings = {ATTRIBUTES = (Public, ); }; }; B350625D1B0111740018CF92 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943141A1575670030A7D0 /* Photos.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; B350625E1B0111780018CF92 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943121A1575630030A7D0 /* AssetsLibrary.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - BB5FC3CE1F9BA689007F191E /* ASNavigationControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BB5FC3CD1F9BA688007F191E /* ASNavigationControllerTests.m */; }; - BB5FC3D11F9C9389007F191E /* ASTabBarControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BB5FC3D01F9C9389007F191E /* ASTabBarControllerTests.m */; }; - C057D9BD20B5453D00FC9112 /* ASTextNode2SnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C057D9BC20B5453D00FC9112 /* ASTextNode2SnapshotTests.m */; }; + BB5FC3CE1F9BA689007F191E /* ASNavigationControllerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB5FC3CD1F9BA688007F191E /* ASNavigationControllerTests.mm */; }; + BB5FC3D11F9C9389007F191E /* ASTabBarControllerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB5FC3D01F9C9389007F191E /* ASTabBarControllerTests.mm */; }; + C018DF21216BF26700181FDA /* ASAbstractLayoutController+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = C018DF20216BF26600181FDA /* ASAbstractLayoutController+FrameworkPrivate.h */; }; + C057D9BD20B5453D00FC9112 /* ASTextNode2SnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = C057D9BC20B5453D00FC9112 /* ASTextNode2SnapshotTests.mm */; }; C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC034A091E60BEB400626263 /* ASDisplayNode+Convenience.h in Headers */ = {isa = PBXBuildFile; fileRef = CC034A071E60BEB400626263 /* ASDisplayNode+Convenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CC034A0A1E60BEB400626263 /* ASDisplayNode+Convenience.m in Sources */ = {isa = PBXBuildFile; fileRef = CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.m */; }; + CC034A0A1E60BEB400626263 /* ASDisplayNode+Convenience.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.mm */; }; CC034A131E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = CC034A111E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CC034A141E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.m in Sources */ = {isa = PBXBuildFile; fileRef = CC034A121E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.m */; }; - CC051F1F1D7A286A006434CB /* ASCALayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC051F1E1D7A286A006434CB /* ASCALayerTests.m */; }; - CC0AEEA41D66316E005D1C78 /* ASUICollectionViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.m */; }; - CC0F885B1E42807F00576FED /* ASCollectionViewFlowLayoutInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0F88591E42807F00576FED /* ASCollectionViewFlowLayoutInspector.m */; }; + CC034A141E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC034A121E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.mm */; }; + CC051F1F1D7A286A006434CB /* ASCALayerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC051F1E1D7A286A006434CB /* ASCALayerTests.mm */; }; + CC0AEEA41D66316E005D1C78 /* ASUICollectionViewTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.mm */; }; + CC0F885B1E42807F00576FED /* ASCollectionViewFlowLayoutInspector.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC0F88591E42807F00576FED /* ASCollectionViewFlowLayoutInspector.mm */; }; CC0F885C1E42807F00576FED /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0F885A1E42807F00576FED /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Private, ); }; }; - CC0F885F1E4280B800576FED /* _ASCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0F885D1E4280B800576FED /* _ASCollectionViewCell.m */; }; + CC0F885F1E4280B800576FED /* _ASCollectionViewCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC0F885D1E4280B800576FED /* _ASCollectionViewCell.mm */; }; CC0F88601E4280B800576FED /* _ASCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0F885E1E4280B800576FED /* _ASCollectionViewCell.h */; settings = {ATTRIBUTES = (Private, ); }; }; CC0F88621E4281E200576FED /* ASSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = CCE04B1E1E313EA7006AEBBB /* ASSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC0F88631E4281E700576FED /* ASSupplementaryNodeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = CCE04B2B1E314A32006AEBBB /* ASSupplementaryNodeSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC0F886C1E4286FA00576FED /* ReferenceImages_64 in Resources */ = {isa = PBXBuildFile; fileRef = CC0F88691E4286FA00576FED /* ReferenceImages_64 */; }; CC0F886D1E4286FA00576FED /* ReferenceImages_iOS_10 in Resources */ = {isa = PBXBuildFile; fileRef = CC0F886A1E4286FA00576FED /* ReferenceImages_iOS_10 */; }; - CC11F97A1DB181180024D77B /* ASNetworkImageNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC11F9791DB181180024D77B /* ASNetworkImageNodeTests.m */; }; + CC11F97A1DB181180024D77B /* ASNetworkImageNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC11F9791DB181180024D77B /* ASNetworkImageNodeTests.mm */; }; CC18248C200D49C800875940 /* ASTextNodeCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = CC18248B200D49C800875940 /* ASTextNodeCommon.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC224E962066CA6D00BBA57F /* configuration.json in Resources */ = {isa = PBXBuildFile; fileRef = CC224E952066CA6D00BBA57F /* configuration.json */; }; CC2F65EE1E5FFB1600DA57C9 /* ASMutableElementMap.h in Headers */ = {isa = PBXBuildFile; fileRef = CC2F65EC1E5FFB1600DA57C9 /* ASMutableElementMap.h */; }; - CC2F65EF1E5FFB1600DA57C9 /* ASMutableElementMap.m in Sources */ = {isa = PBXBuildFile; fileRef = CC2F65ED1E5FFB1600DA57C9 /* ASMutableElementMap.m */; }; + CC2F65EF1E5FFB1600DA57C9 /* ASMutableElementMap.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC2F65ED1E5FFB1600DA57C9 /* ASMutableElementMap.mm */; }; CC35CEC320DD7F600006448D /* ASCollections.h in Headers */ = {isa = PBXBuildFile; fileRef = CC35CEC120DD7F600006448D /* ASCollections.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CC35CEC420DD7F600006448D /* ASCollections.m in Sources */ = {isa = PBXBuildFile; fileRef = CC35CEC220DD7F600006448D /* ASCollections.m */; }; - CC35CEC620DD87280006448D /* ASCollectionsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC35CEC520DD87280006448D /* ASCollectionsTests.m */; }; + CC35CEC420DD7F600006448D /* ASCollections.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC35CEC220DD7F600006448D /* ASCollections.mm */; }; + CC35CEC620DD87280006448D /* ASCollectionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC35CEC520DD87280006448D /* ASCollectionsTests.mm */; }; + CC36C18F218B841600232F23 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C18E218B841600232F23 /* UIKit.framework */; }; + CC36C191218B841A00232F23 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C190218B841A00232F23 /* CoreText.framework */; }; + CC36C193218B842E00232F23 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C192218B842E00232F23 /* CoreGraphics.framework */; }; + CC36C194218B844800232F23 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AF195D04C000B7D73C /* Foundation.framework */; }; + CC36C196218B845B00232F23 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C195218B845B00232F23 /* AVFoundation.framework */; }; + CC36C198218B846300232F23 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C197218B846300232F23 /* QuartzCore.framework */; }; + CC36C19A218B846F00232F23 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C199218B846F00232F23 /* CoreLocation.framework */; }; + CC36C19C218B847400232F23 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C19B218B847400232F23 /* CoreMedia.framework */; }; + CC36C19D218B849C00232F23 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C18E218B841600232F23 /* UIKit.framework */; }; + CC36C19E218B894400232F23 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C195218B845B00232F23 /* AVFoundation.framework */; }; + CC36C19F218B894800232F23 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC36C19B218B847400232F23 /* CoreMedia.framework */; }; CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; settings = {ATTRIBUTES = (Private, ); }; }; CC3B20861C3F76D600798563 /* ASPendingStateController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20821C3F76D600798563 /* ASPendingStateController.mm */; }; CC3B208A1C3F7A5400798563 /* ASWeakSet.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20871C3F7A5400798563 /* ASWeakSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CC3B208C1C3F7A5400798563 /* ASWeakSet.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20881C3F7A5400798563 /* ASWeakSet.m */; }; - CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.m */; }; + CC3B208C1C3F7A5400798563 /* ASWeakSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20881C3F7A5400798563 /* ASWeakSet.mm */; }; + CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.mm */; }; CC3B20901C3F892D00798563 /* ASBridgedPropertiesTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B208F1C3F892D00798563 /* ASBridgedPropertiesTests.mm */; }; - CC4981B31D1A02BE004E13CC /* ASTableViewThrashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC4981B21D1A02BE004E13CC /* ASTableViewThrashTests.m */; }; + CC4981B31D1A02BE004E13CC /* ASTableViewThrashTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC4981B21D1A02BE004E13CC /* ASTableViewThrashTests.mm */; }; CC4C2A771D88E3BF0039ACAB /* ASTraceEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4C2A751D88E3BF0039ACAB /* ASTraceEvent.h */; settings = {ATTRIBUTES = (Private, ); }; }; - CC4C2A791D88E3BF0039ACAB /* ASTraceEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = CC4C2A761D88E3BF0039ACAB /* ASTraceEvent.m */; }; + CC4C2A791D88E3BF0039ACAB /* ASTraceEvent.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC4C2A761D88E3BF0039ACAB /* ASTraceEvent.mm */; }; CC54A81C1D70079800296A24 /* ASDispatch.h in Headers */ = {isa = PBXBuildFile; fileRef = CC54A81B1D70077A00296A24 /* ASDispatch.h */; settings = {ATTRIBUTES = (Private, ); }; }; - CC54A81E1D7008B300296A24 /* ASDispatchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC54A81D1D7008B300296A24 /* ASDispatchTests.m */; }; + CC54A81E1D7008B300296A24 /* ASDispatchTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC54A81D1D7008B300296A24 /* ASDispatchTests.mm */; }; CC55A70D1E529FA200594372 /* UIResponder+AsyncDisplayKit.h in Headers */ = {isa = PBXBuildFile; fileRef = CC55A70B1E529FA200594372 /* UIResponder+AsyncDisplayKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CC55A70E1E529FA200594372 /* UIResponder+AsyncDisplayKit.m in Sources */ = {isa = PBXBuildFile; fileRef = CC55A70C1E529FA200594372 /* UIResponder+AsyncDisplayKit.m */; }; + CC55A70E1E529FA200594372 /* UIResponder+AsyncDisplayKit.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC55A70C1E529FA200594372 /* UIResponder+AsyncDisplayKit.mm */; }; CC55A7111E52A0F200594372 /* ASResponderChainEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = CC55A70F1E52A0F200594372 /* ASResponderChainEnumerator.h */; }; - CC55A7121E52A0F200594372 /* ASResponderChainEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = CC55A7101E52A0F200594372 /* ASResponderChainEnumerator.m */; }; + CC55A7121E52A0F200594372 /* ASResponderChainEnumerator.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC55A7101E52A0F200594372 /* ASResponderChainEnumerator.mm */; }; CC56013B1F06E9A700DC4FBE /* ASIntegerMap.h in Headers */ = {isa = PBXBuildFile; fileRef = CC5601391F06E9A700DC4FBE /* ASIntegerMap.h */; }; CC56013C1F06E9A700DC4FBE /* ASIntegerMap.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC56013A1F06E9A700DC4FBE /* ASIntegerMap.mm */; }; CC57EAF71E3939350034C595 /* ASCollectionView+Undeprecated.h in Headers */ = {isa = PBXBuildFile; fileRef = CC2E317F1DAC353700EEE891 /* ASCollectionView+Undeprecated.h */; settings = {ATTRIBUTES = (Private, ); }; }; CC57EAF81E3939450034C595 /* ASTableView+Undeprecated.h in Headers */ = {isa = PBXBuildFile; fileRef = CC512B841DAC45C60054848E /* ASTableView+Undeprecated.h */; settings = {ATTRIBUTES = (Private, ); }; }; - CC583AD61EF9BDBE00134156 /* ASTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = CC583AC21EF9BAB400134156 /* ASTestCase.m */; }; - CC583AD71EF9BDC100134156 /* NSInvocation+ASTestHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = CC583AC51EF9BAB400134156 /* NSInvocation+ASTestHelpers.m */; }; - CC583AD81EF9BDC300134156 /* OCMockObject+ASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CC583AC71EF9BAB400134156 /* OCMockObject+ASAdditions.m */; }; - CC583AD91EF9BDC600134156 /* ASDisplayNode+OCMock.m in Sources */ = {isa = PBXBuildFile; fileRef = CC583AC01EF9BAB400134156 /* ASDisplayNode+OCMock.m */; }; + CC583AD61EF9BDBE00134156 /* ASTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC583AC21EF9BAB400134156 /* ASTestCase.mm */; }; + CC583AD71EF9BDC100134156 /* NSInvocation+ASTestHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC583AC51EF9BAB400134156 /* NSInvocation+ASTestHelpers.mm */; }; + CC583AD81EF9BDC300134156 /* OCMockObject+ASAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC583AC71EF9BAB400134156 /* OCMockObject+ASAdditions.mm */; }; + CC583AD91EF9BDC600134156 /* ASDisplayNode+OCMock.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC583AC01EF9BAB400134156 /* ASDisplayNode+OCMock.mm */; }; CC58AA4B1E398E1D002C8CB4 /* ASBlockTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = CC58AA4A1E398E1D002C8CB4 /* ASBlockTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC6AA2DA1E9F03B900978E87 /* ASDisplayNode+Ancestry.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6AA2D81E9F03B900978E87 /* ASDisplayNode+Ancestry.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CC6AA2DB1E9F03B900978E87 /* ASDisplayNode+Ancestry.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6AA2D91E9F03B900978E87 /* ASDisplayNode+Ancestry.m */; }; + CC6AA2DB1E9F03B900978E87 /* ASDisplayNode+Ancestry.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC6AA2D91E9F03B900978E87 /* ASDisplayNode+Ancestry.mm */; }; CC7AF196200D9BD500A21BDE /* ASExperimentalFeatures.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7AF195200D9BD500A21BDE /* ASExperimentalFeatures.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CC7AF198200DAB2200A21BDE /* ASExperimentalFeatures.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7AF197200D9E8400A21BDE /* ASExperimentalFeatures.m */; }; - CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */; }; + CC7AF198200DAB2200A21BDE /* ASExperimentalFeatures.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC7AF197200D9E8400A21BDE /* ASExperimentalFeatures.mm */; }; + CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.mm */; }; CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC84C7F220474C5300A3851B /* ASCGImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = CC84C7F020474C5300A3851B /* ASCGImageBuffer.h */; }; - CC84C7F320474C5300A3851B /* ASCGImageBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = CC84C7F120474C5300A3851B /* ASCGImageBuffer.m */; }; + CC84C7F320474C5300A3851B /* ASCGImageBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC84C7F120474C5300A3851B /* ASCGImageBuffer.mm */; }; CC87BB951DA8193C0090E380 /* ASCellNode+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = CC87BB941DA8193C0090E380 /* ASCellNode+Internal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - CC8B05D61D73836400F54286 /* ASPerformanceTestContext.m in Sources */ = {isa = PBXBuildFile; fileRef = CC8B05D51D73836400F54286 /* ASPerformanceTestContext.m */; }; - CC8B05D81D73979700F54286 /* ASTextNodePerformanceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.m */; }; + CC8B05D61D73836400F54286 /* ASPerformanceTestContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC8B05D51D73836400F54286 /* ASPerformanceTestContext.mm */; }; + CC8B05D81D73979700F54286 /* ASTextNodePerformanceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.mm */; }; CC90E1F41E383C0400FED591 /* AsyncDisplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B35061DA1B010EDF0018CF92 /* AsyncDisplayKit.framework */; }; - CCA221D31D6FA7EF00AF6A0F /* ASViewControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.m */; }; + CCA221D31D6FA7EF00AF6A0F /* ASViewControllerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.mm */; }; CCA282B41E9EA7310037E8B7 /* ASTipsController.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282B21E9EA7310037E8B7 /* ASTipsController.h */; }; - CCA282B51E9EA7310037E8B7 /* ASTipsController.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282B31E9EA7310037E8B7 /* ASTipsController.m */; }; + CCA282B51E9EA7310037E8B7 /* ASTipsController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA282B31E9EA7310037E8B7 /* ASTipsController.mm */; }; CCA282B81E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282B61E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CCA282B91E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282B71E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.m */; }; + CCA282B91E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA282B71E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.mm */; }; CCA282BC1E9EABDD0037E8B7 /* ASTipProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282BA1E9EABDD0037E8B7 /* ASTipProvider.h */; }; - CCA282BD1E9EABDD0037E8B7 /* ASTipProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282BB1E9EABDD0037E8B7 /* ASTipProvider.m */; }; + CCA282BD1E9EABDD0037E8B7 /* ASTipProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA282BB1E9EABDD0037E8B7 /* ASTipProvider.mm */; }; CCA282C01E9EAE010037E8B7 /* ASTip.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282BE1E9EAE010037E8B7 /* ASTip.h */; }; - CCA282C11E9EAE010037E8B7 /* ASTip.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282BF1E9EAE010037E8B7 /* ASTip.m */; }; + CCA282C11E9EAE010037E8B7 /* ASTip.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA282BF1E9EAE010037E8B7 /* ASTip.mm */; }; CCA282C41E9EAE630037E8B7 /* ASLayerBackingTipProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282C21E9EAE630037E8B7 /* ASLayerBackingTipProvider.h */; }; - CCA282C51E9EAE630037E8B7 /* ASLayerBackingTipProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282C31E9EAE630037E8B7 /* ASLayerBackingTipProvider.m */; }; + CCA282C51E9EAE630037E8B7 /* ASLayerBackingTipProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA282C31E9EAE630037E8B7 /* ASLayerBackingTipProvider.mm */; }; CCA282C81E9EB64B0037E8B7 /* ASDisplayNodeTipState.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282C61E9EB64B0037E8B7 /* ASDisplayNodeTipState.h */; }; - CCA282C91E9EB64B0037E8B7 /* ASDisplayNodeTipState.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282C71E9EB64B0037E8B7 /* ASDisplayNodeTipState.m */; }; + CCA282C91E9EB64B0037E8B7 /* ASDisplayNodeTipState.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA282C71E9EB64B0037E8B7 /* ASDisplayNodeTipState.mm */; }; CCA282CC1E9EB73E0037E8B7 /* ASTipNode.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282CA1E9EB73E0037E8B7 /* ASTipNode.h */; }; - CCA282CD1E9EB73E0037E8B7 /* ASTipNode.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282CB1E9EB73E0037E8B7 /* ASTipNode.m */; }; + CCA282CD1E9EB73E0037E8B7 /* ASTipNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA282CB1E9EB73E0037E8B7 /* ASTipNode.mm */; }; CCA282D01E9EBF6C0037E8B7 /* ASTipsWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282CE1E9EBF6C0037E8B7 /* ASTipsWindow.h */; }; - CCA282D11E9EBF6C0037E8B7 /* ASTipsWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.m */; }; - CCA5F62E1EECC2A80060C137 /* ASAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA5F62D1EECC2A80060C137 /* ASAssert.m */; }; + CCA282D11E9EBF6C0037E8B7 /* ASTipsWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.mm */; }; + CCA5F62E1EECC2A80060C137 /* ASAssert.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCA5F62D1EECC2A80060C137 /* ASAssert.mm */; }; CCAA0B7F206ADBF30057B336 /* ASRecursiveUnfairLock.h in Headers */ = {isa = PBXBuildFile; fileRef = CCAA0B7D206ADBF30057B336 /* ASRecursiveUnfairLock.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CCAA0B80206ADBF30057B336 /* ASRecursiveUnfairLock.m in Sources */ = {isa = PBXBuildFile; fileRef = CCAA0B7E206ADBF30057B336 /* ASRecursiveUnfairLock.m */; }; - CCAA0B82206ADECB0057B336 /* ASRecursiveUnfairLockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCAA0B81206ADECB0057B336 /* ASRecursiveUnfairLockTests.m */; }; - CCB1F95A1EFB60A5009C7475 /* ASLog.m in Sources */ = {isa = PBXBuildFile; fileRef = CCB1F9591EFB60A5009C7475 /* ASLog.m */; }; + CCAA0B80206ADBF30057B336 /* ASRecursiveUnfairLock.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCAA0B7E206ADBF30057B336 /* ASRecursiveUnfairLock.mm */; }; + CCAA0B82206ADECB0057B336 /* ASRecursiveUnfairLockTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCAA0B81206ADECB0057B336 /* ASRecursiveUnfairLockTests.mm */; }; + CCB1F95A1EFB60A5009C7475 /* ASLog.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCB1F9591EFB60A5009C7475 /* ASLog.mm */; }; CCB1F95C1EFB6350009C7475 /* ASSignpost.h in Headers */ = {isa = PBXBuildFile; fileRef = CCB1F95B1EFB6316009C7475 /* ASSignpost.h */; }; - CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */; }; + CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.mm */; }; CCBBBF5D1EB161760069AA91 /* ASRangeManagingNode.h in Headers */ = {isa = PBXBuildFile; fileRef = CCBBBF5C1EB161760069AA91 /* ASRangeManagingNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; CCBDDD0520C62A2D00CBA922 /* ASMainThreadDeallocation.h in Headers */ = {isa = PBXBuildFile; fileRef = CCBDDD0320C62A2D00CBA922 /* ASMainThreadDeallocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; CCBDDD0620C62A2D00CBA922 /* ASMainThreadDeallocation.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCBDDD0420C62A2D00CBA922 /* ASMainThreadDeallocation.mm */; }; CCCCCCD51EC3EF060087FE10 /* ASTextDebugOption.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCCCCC31EC3EF060087FE10 /* ASTextDebugOption.h */; }; - CCCCCCD61EC3EF060087FE10 /* ASTextDebugOption.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCC41EC3EF060087FE10 /* ASTextDebugOption.m */; }; + CCCCCCD61EC3EF060087FE10 /* ASTextDebugOption.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCC41EC3EF060087FE10 /* ASTextDebugOption.mm */; }; CCCCCCD71EC3EF060087FE10 /* ASTextInput.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCCCCC51EC3EF060087FE10 /* ASTextInput.h */; }; - CCCCCCD81EC3EF060087FE10 /* ASTextInput.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCC61EC3EF060087FE10 /* ASTextInput.m */; }; + CCCCCCD81EC3EF060087FE10 /* ASTextInput.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCC61EC3EF060087FE10 /* ASTextInput.mm */; }; CCCCCCD91EC3EF060087FE10 /* ASTextLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCCCCC71EC3EF060087FE10 /* ASTextLayout.h */; }; - CCCCCCDA1EC3EF060087FE10 /* ASTextLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCC81EC3EF060087FE10 /* ASTextLayout.m */; }; + CCCCCCDA1EC3EF060087FE10 /* ASTextLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCC81EC3EF060087FE10 /* ASTextLayout.mm */; }; CCCCCCDB1EC3EF060087FE10 /* ASTextLine.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCCCCC91EC3EF060087FE10 /* ASTextLine.h */; }; - CCCCCCDC1EC3EF060087FE10 /* ASTextLine.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCCA1EC3EF060087FE10 /* ASTextLine.m */; }; + CCCCCCDC1EC3EF060087FE10 /* ASTextLine.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCCA1EC3EF060087FE10 /* ASTextLine.mm */; }; CCCCCCDD1EC3EF060087FE10 /* ASTextAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCCCCCC1EC3EF060087FE10 /* ASTextAttribute.h */; }; - CCCCCCDE1EC3EF060087FE10 /* ASTextAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCCD1EC3EF060087FE10 /* ASTextAttribute.m */; }; + CCCCCCDE1EC3EF060087FE10 /* ASTextAttribute.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCCD1EC3EF060087FE10 /* ASTextAttribute.mm */; }; CCCCCCDF1EC3EF060087FE10 /* ASTextRunDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCCCCCE1EC3EF060087FE10 /* ASTextRunDelegate.h */; }; - CCCCCCE01EC3EF060087FE10 /* ASTextRunDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCCF1EC3EF060087FE10 /* ASTextRunDelegate.m */; }; + CCCCCCE01EC3EF060087FE10 /* ASTextRunDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCCF1EC3EF060087FE10 /* ASTextRunDelegate.mm */; }; CCCCCCE11EC3EF060087FE10 /* ASTextUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCCCCD11EC3EF060087FE10 /* ASTextUtilities.h */; }; - CCCCCCE21EC3EF060087FE10 /* ASTextUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCD21EC3EF060087FE10 /* ASTextUtilities.m */; }; + CCCCCCE21EC3EF060087FE10 /* ASTextUtilities.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCD21EC3EF060087FE10 /* ASTextUtilities.mm */; }; CCCCCCE31EC3EF060087FE10 /* NSParagraphStyle+ASText.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCCCCD31EC3EF060087FE10 /* NSParagraphStyle+ASText.h */; }; - CCCCCCE41EC3EF060087FE10 /* NSParagraphStyle+ASText.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCD41EC3EF060087FE10 /* NSParagraphStyle+ASText.m */; }; + CCCCCCE41EC3EF060087FE10 /* NSParagraphStyle+ASText.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCD41EC3EF060087FE10 /* NSParagraphStyle+ASText.mm */; }; CCCCCCE71EC3F0FC0087FE10 /* NSAttributedString+ASText.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCCCCE51EC3F0FC0087FE10 /* NSAttributedString+ASText.h */; }; - CCCCCCE81EC3F0FC0087FE10 /* NSAttributedString+ASText.m in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCE61EC3F0FC0087FE10 /* NSAttributedString+ASText.m */; }; + CCCCCCE81EC3F0FC0087FE10 /* NSAttributedString+ASText.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCCCCCE61EC3F0FC0087FE10 /* NSAttributedString+ASText.mm */; }; CCDC9B4D200991D10063C1F8 /* ASGraphicsContext.h in Headers */ = {isa = PBXBuildFile; fileRef = CCDC9B4B200991D10063C1F8 /* ASGraphicsContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CCDC9B4E200991D10063C1F8 /* ASGraphicsContext.m in Sources */ = {isa = PBXBuildFile; fileRef = CCDC9B4C200991D10063C1F8 /* ASGraphicsContext.m */; }; - CCDD148B1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCDD148A1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.m */; }; - CCE4F9B31F0D60AC00062E4E /* ASIntegerMapTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCE4F9B21F0D60AC00062E4E /* ASIntegerMapTests.m */; }; + CCDC9B4E200991D10063C1F8 /* ASGraphicsContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCDC9B4C200991D10063C1F8 /* ASGraphicsContext.mm */; }; + CCDD148B1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCDD148A1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.mm */; }; + CCE4F9B31F0D60AC00062E4E /* ASIntegerMapTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCE4F9B21F0D60AC00062E4E /* ASIntegerMapTests.mm */; }; CCE4F9B51F0DA4F300062E4E /* ASLayoutEngineTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCE4F9B41F0DA4F300062E4E /* ASLayoutEngineTests.mm */; }; CCE4F9BA1F0DBB5000062E4E /* ASLayoutTestNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCE4F9B71F0DBA5000062E4E /* ASLayoutTestNode.mm */; }; CCE4F9BE1F0ECE5200062E4E /* ASTLayoutFixture.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCE4F9BD1F0ECE5200062E4E /* ASTLayoutFixture.mm */; }; CCED5E3E2020D36800395C40 /* ASNetworkImageLoadInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = CCED5E3C2020D36800395C40 /* ASNetworkImageLoadInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CCED5E3F2020D36800395C40 /* ASNetworkImageLoadInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = CCED5E3D2020D36800395C40 /* ASNetworkImageLoadInfo.m */; }; + CCED5E3F2020D36800395C40 /* ASNetworkImageLoadInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCED5E3D2020D36800395C40 /* ASNetworkImageLoadInfo.mm */; }; CCED5E412020D49D00395C40 /* ASNetworkImageLoadInfo+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CCED5E402020D41600395C40 /* ASNetworkImageLoadInfo+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; CCEDDDCA200C2AC300FFCD0A /* ASConfigurationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = CCEDDDC8200C2AC300FFCD0A /* ASConfigurationInternal.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CCEDDDCB200C2AC300FFCD0A /* ASConfigurationInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDC9200C2AC300FFCD0A /* ASConfigurationInternal.m */; }; + CCEDDDCB200C2AC300FFCD0A /* ASConfigurationInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDC9200C2AC300FFCD0A /* ASConfigurationInternal.mm */; }; CCEDDDCD200C2CB900FFCD0A /* ASConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = CCEDDDCC200C2CB900FFCD0A /* ASConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; CCEDDDCF200C42A200FFCD0A /* ASConfigurationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = CCEDDDCE200C42A200FFCD0A /* ASConfigurationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CCEDDDD1200C488000FFCD0A /* ASConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDD0200C488000FFCD0A /* ASConfiguration.m */; }; - CCEDDDD9200C518800FFCD0A /* ASConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.m */; }; + CCEDDDD1200C488000FFCD0A /* ASConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDD0200C488000FFCD0A /* ASConfiguration.mm */; }; + CCEDDDD9200C518800FFCD0A /* ASConfigurationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.mm */; }; CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; }; CCF1FF5E20C4785000AAD8FC /* ASLocking.h in Headers */ = {isa = PBXBuildFile; fileRef = CCF1FF5D20C4785000AAD8FC /* ASLocking.h */; settings = {ATTRIBUTES = (Public, ); }; }; DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; }; DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; }; - DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.m in Sources */ = {isa = PBXBuildFile; fileRef = DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.m */; }; + DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.mm */; }; DBABFAFC1C6A8D2F0039EA4A /* _ASTransitionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; - DBC452DE1C5C6A6A00B16017 /* ArrayDiffingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DBC452DD1C5C6A6A00B16017 /* ArrayDiffingTests.m */; }; - DBC453221C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.m */; }; + DBC452DE1C5C6A6A00B16017 /* ArrayDiffingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DBC452DD1C5C6A6A00B16017 /* ArrayDiffingTests.mm */; }; + DBC453221C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.mm */; }; DBDB83951C6E879900D0098C /* ASPagerFlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = DBDB83921C6E879900D0098C /* ASPagerFlowLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DBDB83971C6E879900D0098C /* ASPagerFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = DBDB83931C6E879900D0098C /* ASPagerFlowLayout.m */; }; + DBDB83971C6E879900D0098C /* ASPagerFlowLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = DBDB83931C6E879900D0098C /* ASPagerFlowLayout.mm */; }; DE4843DC1C93EAC100A1F33B /* ASLayoutTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = E52405B41C8FEF16004DC8E7 /* ASLayoutTransition.h */; settings = {ATTRIBUTES = (Private, ); }; }; DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; DE84918D1C8FFF2B003D89E9 /* ASRunLoopQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 81EE384D1C8E94F000456208 /* ASRunLoopQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; DE84918E1C8FFF9F003D89E9 /* ASRunLoopQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 81EE384E1C8E94F000456208 /* ASRunLoopQueue.mm */; }; DE8BEAC21C2DF3FC00D57C12 /* ASDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; - DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */; }; + DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.mm */; }; DEB8ED7C1DD003D300DBDE55 /* ASLayoutTransition.mm in Sources */ = {isa = PBXBuildFile; fileRef = E52405B21C8FEF03004DC8E7 /* ASLayoutTransition.mm */; }; DEC146B71C37A16A004A0EE7 /* ASCollectionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DEC146B41C37A16A004A0EE7 /* ASCollectionInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - DEC146B91C37A16A004A0EE7 /* ASCollectionInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = DEC146B51C37A16A004A0EE7 /* ASCollectionInternal.m */; }; DECBD6E81BE56E1900CF4905 /* ASButtonNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; DECBD6EA1BE56E1900CF4905 /* ASButtonNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */; }; DEFAD8131CC48914000527C4 /* ASVideoNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = AEEC47E01C20C2DD00EC1693 /* ASVideoNode.mm */; }; - E51B78BF1F028ABF00E32604 /* ASLayoutFlatteningTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E51B78BD1F01A0EE00E32604 /* ASLayoutFlatteningTests.m */; }; + E51B78BF1F028ABF00E32604 /* ASLayoutFlatteningTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = E51B78BD1F01A0EE00E32604 /* ASLayoutFlatteningTests.mm */; }; E54E00721F1D3828000B30D7 /* ASPagerNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = E54E00711F1D3828000B30D7 /* ASPagerNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; E54E81FC1EB357BD00FFE8E1 /* ASPageTable.h in Headers */ = {isa = PBXBuildFile; fileRef = E54E81FA1EB357BD00FFE8E1 /* ASPageTable.h */; }; - E54E81FD1EB357BD00FFE8E1 /* ASPageTable.m in Sources */ = {isa = PBXBuildFile; fileRef = E54E81FB1EB357BD00FFE8E1 /* ASPageTable.m */; }; + E54E81FD1EB357BD00FFE8E1 /* ASPageTable.mm in Sources */ = {isa = PBXBuildFile; fileRef = E54E81FB1EB357BD00FFE8E1 /* ASPageTable.mm */; }; E55D86331CA8A14000A0C26F /* ASLayoutElement.mm in Sources */ = {isa = PBXBuildFile; fileRef = E55D86311CA8A14000A0C26F /* ASLayoutElement.mm */; }; E5667E8C1F33871300FA6FC0 /* _ASCollectionGalleryLayoutInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = E5667E8B1F33871300FA6FC0 /* _ASCollectionGalleryLayoutInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - E5667E8E1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = E5667E8D1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.m */; }; + E5667E8E1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5667E8D1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.mm */; }; E5711A2C1C840C81009619D4 /* ASCollectionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E5711A2A1C840C81009619D4 /* ASCollectionElement.h */; settings = {ATTRIBUTES = (Private, ); }; }; E5711A301C840C96009619D4 /* ASCollectionElement.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5711A2D1C840C96009619D4 /* ASCollectionElement.mm */; }; E5775AFC1F13CE9F00CAC9BC /* _ASCollectionGalleryLayoutItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E5775AFB1F13CE9F00CAC9BC /* _ASCollectionGalleryLayoutItem.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -471,21 +480,21 @@ E5775B001F13D25400CAC9BC /* ASCollectionLayoutState+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = E5775AFF1F13D25400CAC9BC /* ASCollectionLayoutState+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; E5775B021F16759300CAC9BC /* ASCollectionLayoutCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E5775B011F16759300CAC9BC /* ASCollectionLayoutCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; E5775B041F16759F00CAC9BC /* ASCollectionLayoutCache.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5775B031F16759F00CAC9BC /* ASCollectionLayoutCache.mm */; }; - E5855DEF1EBB4D83003639AE /* ASCollectionLayoutDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = E5855DED1EBB4D83003639AE /* ASCollectionLayoutDefines.m */; }; + E5855DEF1EBB4D83003639AE /* ASCollectionLayoutDefines.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5855DED1EBB4D83003639AE /* ASCollectionLayoutDefines.mm */; }; E5855DF01EBB4D83003639AE /* ASCollectionLayoutDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = E5855DEE1EBB4D83003639AE /* ASCollectionLayoutDefines.h */; settings = {ATTRIBUTES = (Private, ); }; }; - E586F96C1F9F9E2900ECE00E /* ASScrollNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E586F96B1F9F9E2900ECE00E /* ASScrollNodeTests.m */; }; + E586F96C1F9F9E2900ECE00E /* ASScrollNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = E586F96B1F9F9E2900ECE00E /* ASScrollNodeTests.mm */; }; E58E9E421E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E58E9E3D1E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E58E9E431E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E58E9E3E1E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.m */; }; + E58E9E431E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E58E9E3E1E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.mm */; }; E58E9E441E941D74004CFC59 /* ASCollectionLayoutContext.h in Headers */ = {isa = PBXBuildFile; fileRef = E58E9E3F1E941D74004CFC59 /* ASCollectionLayoutContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E58E9E451E941D74004CFC59 /* ASCollectionLayoutContext.m in Sources */ = {isa = PBXBuildFile; fileRef = E58E9E401E941D74004CFC59 /* ASCollectionLayoutContext.m */; }; + E58E9E451E941D74004CFC59 /* ASCollectionLayoutContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = E58E9E401E941D74004CFC59 /* ASCollectionLayoutContext.mm */; }; E58E9E461E941D74004CFC59 /* ASCollectionLayoutDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E58E9E411E941D74004CFC59 /* ASCollectionLayoutDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; E58E9E491E941DA5004CFC59 /* ASCollectionLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = E58E9E471E941DA5004CFC59 /* ASCollectionLayout.h */; settings = {ATTRIBUTES = (Private, ); }; }; E58E9E4A1E941DA5004CFC59 /* ASCollectionLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = E58E9E481E941DA5004CFC59 /* ASCollectionLayout.mm */; }; E5B077FF1E69F4EB00C24B5B /* ASElementMap.h in Headers */ = {isa = PBXBuildFile; fileRef = E5B077FD1E69F4EB00C24B5B /* ASElementMap.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E5B078001E69F4EB00C24B5B /* ASElementMap.m in Sources */ = {isa = PBXBuildFile; fileRef = E5B077FE1E69F4EB00C24B5B /* ASElementMap.m */; }; + E5B078001E69F4EB00C24B5B /* ASElementMap.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5B077FE1E69F4EB00C24B5B /* ASElementMap.mm */; }; E5B225281F1790D6001E1431 /* ASHashing.h in Headers */ = {isa = PBXBuildFile; fileRef = E5B225271F1790B5001E1431 /* ASHashing.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E5B225291F1790EE001E1431 /* ASHashing.m in Sources */ = {isa = PBXBuildFile; fileRef = E5B225261F1790B5001E1431 /* ASHashing.m */; }; - E5B2252E1F17E521001E1431 /* ASDispatch.m in Sources */ = {isa = PBXBuildFile; fileRef = E5B2252D1F17E521001E1431 /* ASDispatch.m */; }; + E5B225291F1790EE001E1431 /* ASHashing.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5B225261F1790B5001E1431 /* ASHashing.mm */; }; + E5B2252E1F17E521001E1431 /* ASDispatch.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5B2252D1F17E521001E1431 /* ASDispatch.mm */; }; E5B5B9D11E9BAD9800A6B726 /* ASCollectionLayoutContext+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = E5B5B9D01E9BAD9800A6B726 /* ASCollectionLayoutContext+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; E5C347B11ECB3D9200EC4BE4 /* ASBatchFetchingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E5C347B01ECB3D9200EC4BE4 /* ASBatchFetchingDelegate.h */; }; E5C347B31ECB40AA00EC4BE4 /* ASTableNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = E5C347B21ECB40AA00EC4BE4 /* ASTableNode+Beta.h */; }; @@ -493,8 +502,10 @@ E5E281761E71C845006B67C2 /* ASCollectionLayoutState.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5E281751E71C845006B67C2 /* ASCollectionLayoutState.mm */; }; E5E2D72E1EA780C4005C24C6 /* ASCollectionGalleryLayoutDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E5E2D72D1EA780C4005C24C6 /* ASCollectionGalleryLayoutDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; E5E2D7301EA780DF005C24C6 /* ASCollectionGalleryLayoutDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5E2D72F1EA780DF005C24C6 /* ASCollectionGalleryLayoutDelegate.mm */; }; + F325E48C21745F9E00AC93A4 /* ASButtonNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F325E48B21745F9E00AC93A4 /* ASButtonNodeTests.mm */; }; + F325E490217460B100AC93A4 /* ASTextNode2Tests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F325E48F217460B000AC93A4 /* ASTextNode2Tests.mm */; }; F3F698D2211CAD4600800CB1 /* ASDisplayViewAccessibilityTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F3F698D1211CAD4600800CB1 /* ASDisplayViewAccessibilityTests.mm */; }; - F711994E1D20C21100568860 /* ASDisplayNodeExtrasTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F711994D1D20C21100568860 /* ASDisplayNodeExtrasTests.m */; }; + F711994E1D20C21100568860 /* ASDisplayNodeExtrasTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F711994D1D20C21100568860 /* ASDisplayNodeExtrasTests.mm */; }; FA4FAF15200A850200E735BD /* ASControlNode+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = FA4FAF14200A850200E735BD /* ASControlNode+Private.h */; }; /* End PBXBuildFile section */ @@ -511,16 +522,16 @@ /* Begin PBXFileReference section */ 044285011BAA3CC700D16268 /* AsyncDisplayKit.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = AsyncDisplayKit.modulemap; sourceTree = ""; }; 044285051BAA63FE00D16268 /* ASBatchFetching.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASBatchFetching.h; sourceTree = ""; }; - 044285061BAA63FE00D16268 /* ASBatchFetching.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASBatchFetching.m; sourceTree = ""; }; + 044285061BAA63FE00D16268 /* ASBatchFetching.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASBatchFetching.mm; sourceTree = ""; }; 0442850B1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTwoDimensionalArrayUtils.h; sourceTree = ""; }; - 0442850C1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTwoDimensionalArrayUtils.m; sourceTree = ""; }; + 0442850C1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTwoDimensionalArrayUtils.mm; sourceTree = ""; }; 0516FA3A1A15563400B4EBED /* ASAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASAvailability.h; sourceTree = ""; }; 0516FA3B1A15563400B4EBED /* ASLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLog.h; sourceTree = ""; }; 0516FA3E1A1563D200B4EBED /* ASMultiplexImageNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMultiplexImageNode.h; sourceTree = ""; }; 0516FA3F1A1563D200B4EBED /* ASMultiplexImageNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMultiplexImageNode.mm; sourceTree = ""; }; 051943121A1575630030A7D0 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; 051943141A1575670030A7D0 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; }; - 052EE0651A159FEF002C6279 /* ASMultiplexImageNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASMultiplexImageNodeTests.m; sourceTree = ""; }; + 052EE0651A159FEF002C6279 /* ASMultiplexImageNodeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMultiplexImageNodeTests.mm; sourceTree = ""; }; 052EE06A1A15A0D8002C6279 /* TestResources */ = {isa = PBXFileReference; lastKnownFileType = folder; path = TestResources; sourceTree = ""; }; 054963471A1EA066000F8E56 /* ASBasicImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASBasicImageDownloader.h; sourceTree = ""; }; 054963481A1EA066000F8E56 /* ASBasicImageDownloader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASBasicImageDownloader.mm; sourceTree = ""; }; @@ -532,13 +543,13 @@ 055F1A3719ABD413004DAFF1 /* ASRangeController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRangeController.mm; sourceTree = ""; }; 055F1A3A19ABD43F004DAFF1 /* ASCellNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCellNode.h; sourceTree = ""; }; 056D21501ABCEDA1001107EF /* ASSnapshotTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASSnapshotTestCase.h; sourceTree = ""; }; - 056D21541ABCEF50001107EF /* ASImageNodeSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASImageNodeSnapshotTests.m; sourceTree = ""; }; + 056D21541ABCEF50001107EF /* ASImageNodeSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASImageNodeSnapshotTests.mm; sourceTree = ""; }; 0574D5E119C110610097DC25 /* ASTableViewProtocols.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASTableViewProtocols.h; sourceTree = ""; }; 057D02BF1AC0A66700C7AC3C /* AsyncDisplayKitTestHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AsyncDisplayKitTestHost.app; sourceTree = BUILT_PRODUCTS_DIR; }; 057D02C21AC0A66700C7AC3C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 057D02C31AC0A66700C7AC3C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 057D02C31AC0A66700C7AC3C /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; 057D02C51AC0A66700C7AC3C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 057D02C61AC0A66700C7AC3C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AppDelegate.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 057D02C61AC0A66700C7AC3C /* AppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = AppDelegate.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 0587F9BB1A7309ED00AFF0BA /* ASEditableTextNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEditableTextNode.h; sourceTree = ""; }; 0587F9BC1A7309ED00AFF0BA /* ASEditableTextNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASEditableTextNode.mm; sourceTree = ""; }; 058D09AF195D04C000B7D73C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -566,16 +577,16 @@ 058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASHighlightOverlayLayer.h; sourceTree = ""; }; 058D09E7195D050800B7D73C /* ASHighlightOverlayLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASHighlightOverlayLayer.mm; sourceTree = ""; }; 058D09E8195D050800B7D73C /* ASMutableAttributedStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMutableAttributedStringBuilder.h; sourceTree = ""; }; - 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASMutableAttributedStringBuilder.m; sourceTree = ""; }; + 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMutableAttributedStringBuilder.mm; sourceTree = ""; }; 058D09F5195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableAttributedString+TextKitAdditions.h"; sourceTree = ""; }; - 058D09F6195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableAttributedString+TextKitAdditions.m"; sourceTree = ""; }; + 058D09F6195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSMutableAttributedString+TextKitAdditions.mm"; sourceTree = ""; }; 058D09F8195D050800B7D73C /* _ASAsyncTransaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASAsyncTransaction.h; sourceTree = ""; }; 058D09F9195D050800B7D73C /* _ASAsyncTransaction.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = _ASAsyncTransaction.mm; sourceTree = ""; }; 058D09FA195D050800B7D73C /* _ASAsyncTransactionContainer+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "_ASAsyncTransactionContainer+Private.h"; sourceTree = ""; }; 058D09FB195D050800B7D73C /* _ASAsyncTransactionContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASAsyncTransactionContainer.h; sourceTree = ""; }; - 058D09FC195D050800B7D73C /* _ASAsyncTransactionContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = _ASAsyncTransactionContainer.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 058D09FC195D050800B7D73C /* _ASAsyncTransactionContainer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = _ASAsyncTransactionContainer.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 058D09FD195D050800B7D73C /* _ASAsyncTransactionGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASAsyncTransactionGroup.h; sourceTree = ""; }; - 058D09FE195D050800B7D73C /* _ASAsyncTransactionGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = _ASAsyncTransactionGroup.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 058D09FE195D050800B7D73C /* _ASAsyncTransactionGroup.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = _ASAsyncTransactionGroup.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 058D09FF195D050800B7D73C /* UIView+ASConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+ASConvenience.h"; sourceTree = ""; }; 058D0A03195D050800B7D73C /* _ASCoreAnimationExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASCoreAnimationExtras.h; sourceTree = ""; }; 058D0A04195D050800B7D73C /* _ASCoreAnimationExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = _ASCoreAnimationExtras.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; @@ -588,20 +599,20 @@ 058D0A0B195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASDisplayNode+UIViewBridge.mm"; sourceTree = ""; }; 058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeInternal.h; sourceTree = ""; }; 058D0A0D195D050800B7D73C /* ASImageNode+CGExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASImageNode+CGExtras.h"; sourceTree = ""; }; - 058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ASImageNode+CGExtras.m"; sourceTree = ""; }; + 058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASImageNode+CGExtras.mm"; sourceTree = ""; }; 058D0A12195D050800B7D73C /* ASThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASThread.h; sourceTree = ""; }; - 058D0A2D195D057000B7D73C /* ASDisplayLayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASDisplayLayerTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 058D0A2E195D057000B7D73C /* ASDisplayNodeAppearanceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASDisplayNodeAppearanceTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 058D0A2D195D057000B7D73C /* ASDisplayLayerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASDisplayLayerTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 058D0A2E195D057000B7D73C /* ASDisplayNodeAppearanceTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASDisplayNodeAppearanceTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 058D0A2F195D057000B7D73C /* ASDisplayNodeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeTests.mm; sourceTree = ""; }; 058D0A30195D057000B7D73C /* ASDisplayNodeTestsHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeTestsHelper.h; sourceTree = ""; }; - 058D0A31195D057000B7D73C /* ASDisplayNodeTestsHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDisplayNodeTestsHelper.m; sourceTree = ""; }; - 058D0A32195D057000B7D73C /* ASMutableAttributedStringBuilderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASMutableAttributedStringBuilderTests.m; sourceTree = ""; }; - 058D0A33195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextKitCoreTextAdditionsTests.m; sourceTree = ""; }; - 058D0A36195D057000B7D73C /* ASTextNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextNodeTests.m; sourceTree = ""; }; + 058D0A31195D057000B7D73C /* ASDisplayNodeTestsHelper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeTestsHelper.mm; sourceTree = ""; }; + 058D0A32195D057000B7D73C /* ASMutableAttributedStringBuilderTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMutableAttributedStringBuilderTests.mm; sourceTree = ""; }; + 058D0A33195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextKitCoreTextAdditionsTests.mm; sourceTree = ""; }; + 058D0A36195D057000B7D73C /* ASTextNodeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextNodeTests.mm; sourceTree = ""; }; 058D0A37195D057000B7D73C /* ASTextNodeWordKernerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextNodeWordKernerTests.mm; sourceTree = ""; }; 058D0A43195D058D00B7D73C /* ASAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASAssert.h; sourceTree = ""; }; 058D0A44195D058D00B7D73C /* ASBaseDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASBaseDefines.h; sourceTree = ""; }; - 05EA6FE61AC0966E00E35788 /* ASSnapshotTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASSnapshotTestCase.m; sourceTree = ""; }; + 05EA6FE61AC0966E00E35788 /* ASSnapshotTestCase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASSnapshotTestCase.mm; sourceTree = ""; }; 05F20AA31A15733C00DCA68A /* ASImageProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASImageProtocols.h; sourceTree = ""; }; 0FAFDF7320EC1C8F003A51C0 /* ASLayout+IGListKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASLayout+IGListKit.h"; sourceTree = ""; }; 0FAFDF7420EC1C90003A51C0 /* ASLayout+IGListKit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASLayout+IGListKit.mm"; sourceTree = ""; }; @@ -612,16 +623,15 @@ 1A6C000C1FAB4E2100D05926 /* ASCornerLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCornerLayoutSpec.mm; sourceTree = ""; }; 1A6C000F1FAB4ED400D05926 /* ASCornerLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCornerLayoutSpecSnapshotTests.mm; sourceTree = ""; }; 205F0E0D1B371875007741D0 /* UICollectionViewLayout+ASConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionViewLayout+ASConvenience.h"; sourceTree = ""; }; - 205F0E0E1B371875007741D0 /* UICollectionViewLayout+ASConvenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionViewLayout+ASConvenience.m"; sourceTree = ""; }; - 205F0E111B371BD7007741D0 /* ASScrollDirection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASScrollDirection.m; sourceTree = ""; }; + 205F0E0E1B371875007741D0 /* UICollectionViewLayout+ASConvenience.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UICollectionViewLayout+ASConvenience.mm"; sourceTree = ""; }; + 205F0E111B371BD7007741D0 /* ASScrollDirection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASScrollDirection.mm; sourceTree = ""; }; 205F0E171B37339C007741D0 /* ASAbstractLayoutController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASAbstractLayoutController.h; sourceTree = ""; }; 205F0E181B37339C007741D0 /* ASAbstractLayoutController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASAbstractLayoutController.mm; sourceTree = ""; }; 205F0E1B1B373A2C007741D0 /* ASCollectionViewLayoutController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionViewLayoutController.h; sourceTree = ""; }; - 205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionViewLayoutController.m; sourceTree = ""; }; + 205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionViewLayoutController.mm; sourceTree = ""; }; 205F0E1F1B376416007741D0 /* CoreGraphics+ASConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CoreGraphics+ASConvenience.h"; sourceTree = ""; }; - 205F0E201B376416007741D0 /* CoreGraphics+ASConvenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CoreGraphics+ASConvenience.m"; sourceTree = ""; }; - 242995D21B29743C00090100 /* ASBasicImageDownloaderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASBasicImageDownloaderTests.m; sourceTree = ""; }; - 2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASCollectionViewFlowLayoutInspectorTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 242995D21B29743C00090100 /* ASBasicImageDownloaderTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASBasicImageDownloaderTests.mm; sourceTree = ""; }; + 2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASCollectionViewFlowLayoutInspectorTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 254C6B511BF8FE6D003EC431 /* ASTextKitTruncationTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextKitTruncationTests.mm; sourceTree = ""; }; 254C6B531BF8FF2A003EC431 /* ASTextKitTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextKitTests.mm; sourceTree = ""; }; 257754931BEE44CD00737CA5 /* ASTextKitRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitRenderer.h; path = TextKit/ASTextKitRenderer.h; sourceTree = ""; }; @@ -630,7 +640,7 @@ 257754961BEE44CD00737CA5 /* ASTextKitContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitContext.h; path = TextKit/ASTextKitContext.h; sourceTree = ""; }; 257754971BEE44CD00737CA5 /* ASTextKitContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitContext.mm; path = TextKit/ASTextKitContext.mm; sourceTree = ""; }; 257754981BEE44CD00737CA5 /* ASTextKitEntityAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitEntityAttribute.h; path = TextKit/ASTextKitEntityAttribute.h; sourceTree = ""; }; - 257754991BEE44CD00737CA5 /* ASTextKitEntityAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextKitEntityAttribute.m; path = TextKit/ASTextKitEntityAttribute.m; sourceTree = ""; }; + 257754991BEE44CD00737CA5 /* ASTextKitEntityAttribute.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitEntityAttribute.mm; path = TextKit/ASTextKitEntityAttribute.mm; sourceTree = ""; }; 2577549A1BEE44CD00737CA5 /* ASTextKitRenderer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitRenderer.mm; path = TextKit/ASTextKitRenderer.mm; sourceTree = ""; }; 2577549B1BEE44CD00737CA5 /* ASTextKitRenderer+Positioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ASTextKitRenderer+Positioning.h"; path = "TextKit/ASTextKitRenderer+Positioning.h"; sourceTree = ""; }; 2577549C1BEE44CD00737CA5 /* ASTextKitRenderer+Positioning.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "ASTextKitRenderer+Positioning.mm"; path = "TextKit/ASTextKitRenderer+Positioning.mm"; sourceTree = ""; }; @@ -642,62 +652,61 @@ 257754A21BEE44CD00737CA5 /* ASTextKitTailTruncater.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitTailTruncater.mm; path = TextKit/ASTextKitTailTruncater.mm; sourceTree = ""; }; 257754A31BEE44CD00737CA5 /* ASTextKitTruncating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitTruncating.h; path = TextKit/ASTextKitTruncating.h; sourceTree = ""; }; 257754B71BEE458D00737CA5 /* ASTextKitComponents.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitComponents.mm; path = TextKit/ASTextKitComponents.mm; sourceTree = ""; }; - 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextKitCoreTextAdditions.m; path = TextKit/ASTextKitCoreTextAdditions.m; sourceTree = ""; }; + 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitCoreTextAdditions.mm; path = TextKit/ASTextKitCoreTextAdditions.mm; sourceTree = ""; }; 257754B91BEE458E00737CA5 /* ASTextNodeWordKerner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextNodeWordKerner.h; path = TextKit/ASTextNodeWordKerner.h; sourceTree = ""; }; 257754BA1BEE458E00737CA5 /* ASTextKitComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitComponents.h; path = TextKit/ASTextKitComponents.h; sourceTree = ""; }; 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitCoreTextAdditions.h; path = TextKit/ASTextKitCoreTextAdditions.h; sourceTree = ""; }; 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextNodeTypes.h; path = TextKit/ASTextNodeTypes.h; sourceTree = ""; }; - 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextNodeWordKerner.m; path = TextKit/ASTextNodeWordKerner.m; sourceTree = ""; }; + 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextNodeWordKerner.mm; path = TextKit/ASTextNodeWordKerner.mm; sourceTree = ""; }; 25E327541C16819500A2170C /* ASPagerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ASPagerNode.h; sourceTree = ""; }; - 25E327551C16819500A2170C /* ASPagerNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASPagerNode.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 2911485B1A77147A005D0878 /* ASControlNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASControlNodeTests.m; sourceTree = ""; }; + 25E327551C16819500A2170C /* ASPagerNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASPagerNode.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 2911485B1A77147A005D0878 /* ASControlNodeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASControlNodeTests.mm; sourceTree = ""; }; 292C59991A956527007E5DD6 /* ASLayoutRangeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutRangeType.h; sourceTree = ""; }; 2967F9E11AB0A4CF0072E4AB /* ASBasicImageDownloaderInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASBasicImageDownloaderInternal.h; sourceTree = ""; }; 296A0A311A951715005ACEAA /* ASScrollDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASScrollDirection.h; path = Source/Details/ASScrollDirection.h; sourceTree = SOURCE_ROOT; }; - 296A0A341A951ABF005ACEAA /* ASBatchFetchingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASBatchFetchingTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 296A0A341A951ABF005ACEAA /* ASBatchFetchingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASBatchFetchingTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 299DA1A71A828D2900162D41 /* ASBatchContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASBatchContext.h; sourceTree = ""; }; - 299DA1A81A828D2900162D41 /* ASBatchContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASBatchContext.m; sourceTree = ""; }; - 29CDC2E11AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASBasicImageDownloaderContextTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 299DA1A81A828D2900162D41 /* ASBatchContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASBatchContext.mm; sourceTree = ""; }; + 29CDC2E11AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASBasicImageDownloaderContextTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 3917EBD21E9C2FC400D04A01 /* _ASCollectionReusableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASCollectionReusableView.h; sourceTree = ""; }; - 3917EBD31E9C2FC400D04A01 /* _ASCollectionReusableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _ASCollectionReusableView.m; sourceTree = ""; }; + 3917EBD31E9C2FC400D04A01 /* _ASCollectionReusableView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASCollectionReusableView.mm; sourceTree = ""; }; 3C9C128419E616EF00E942A0 /* ASTableViewTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASTableViewTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 4496D0721FA9EA6B001CC8D5 /* ASTraitCollectionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASTraitCollectionTests.m; sourceTree = ""; }; 464052191A3F83C40061C0BA /* ASDataController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ASDataController.h; sourceTree = ""; }; 4640521A1A3F83C40061C0BA /* ASDataController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASDataController.mm; sourceTree = ""; }; 4640521B1A3F83C40061C0BA /* ASTableLayoutController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTableLayoutController.h; sourceTree = ""; }; - 4640521C1A3F83C40061C0BA /* ASTableLayoutController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableLayoutController.m; sourceTree = ""; }; + 4640521C1A3F83C40061C0BA /* ASTableLayoutController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTableLayoutController.mm; sourceTree = ""; }; 4640521D1A3F83C40061C0BA /* ASLayoutController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutController.h; sourceTree = ""; }; - 4E9127681F64157600499623 /* ASRunLoopQueueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASRunLoopQueueTests.m; sourceTree = ""; }; + 4E9127681F64157600499623 /* ASRunLoopQueueTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRunLoopQueueTests.mm; sourceTree = ""; }; 68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASImageNode+AnimatedImage.mm"; sourceTree = ""; }; - 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPINRemoteImageDownloader.m; sourceTree = ""; }; + 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPINRemoteImageDownloader.mm; sourceTree = ""; }; 68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASImageContainerProtocolCategories.h; sourceTree = ""; }; - 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASImageContainerProtocolCategories.m; sourceTree = ""; }; + 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASImageContainerProtocolCategories.mm; sourceTree = ""; }; 68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPINRemoteImageDownloader.h; sourceTree = ""; }; 683F563620E409D600CEB7A3 /* ASDisplayNode+InterfaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+InterfaceState.h"; sourceTree = ""; }; 68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+Beta.h"; sourceTree = ""; }; 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASImageNode+AnimatedImagePrivate.h"; sourceTree = ""; }; 68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASWeakProxy.h; sourceTree = ""; }; - 68B8A4E01CBDB958007E4543 /* ASWeakProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakProxy.m; sourceTree = ""; }; + 68B8A4E01CBDB958007E4543 /* ASWeakProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASWeakProxy.mm; sourceTree = ""; }; 68C215561DE10D330019C4BC /* ASCollectionViewLayoutInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionViewLayoutInspector.h; sourceTree = ""; }; - 68C215571DE10D330019C4BC /* ASCollectionViewLayoutInspector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionViewLayoutInspector.m; sourceTree = ""; }; + 68C215571DE10D330019C4BC /* ASCollectionViewLayoutInspector.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionViewLayoutInspector.mm; sourceTree = ""; }; 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMainSerialQueue.h; sourceTree = ""; }; 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMainSerialQueue.mm; sourceTree = ""; }; 68FC85DC1CE29AB700EDD713 /* ASNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASNavigationController.h; sourceTree = ""; }; - 68FC85DD1CE29AB700EDD713 /* ASNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASNavigationController.m; sourceTree = ""; }; + 68FC85DD1CE29AB700EDD713 /* ASNavigationController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASNavigationController.mm; sourceTree = ""; }; 68FC85E01CE29B7E00EDD713 /* ASTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTabBarController.h; sourceTree = ""; }; - 68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTabBarController.m; sourceTree = ""; }; + 68FC85E11CE29B7E00EDD713 /* ASTabBarController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTabBarController.mm; sourceTree = ""; }; 68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASVisibilityProtocols.h; sourceTree = ""; }; - 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASVisibilityProtocols.m; sourceTree = ""; }; + 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASVisibilityProtocols.mm; sourceTree = ""; }; 6900C5F31E8072DA00BCD75C /* ASImageNode+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASImageNode+Private.h"; sourceTree = ""; }; 6907C2561DC4ECFE00374C66 /* ASObjectDescriptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASObjectDescriptionHelpers.h; sourceTree = ""; }; - 6907C2571DC4ECFE00374C66 /* ASObjectDescriptionHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASObjectDescriptionHelpers.m; sourceTree = ""; }; + 6907C2571DC4ECFE00374C66 /* ASObjectDescriptionHelpers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASObjectDescriptionHelpers.mm; sourceTree = ""; }; 690BC8BF20F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeCornerLayerDelegate.h; sourceTree = ""; }; - 690BC8C020F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASDisplayNodeCornerLayerDelegate.m; sourceTree = ""; }; + 690BC8C020F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeCornerLayerDelegate.mm; sourceTree = ""; }; 690C35601E055C5D00069B91 /* ASDimensionInternal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDimensionInternal.mm; sourceTree = ""; }; 690C35631E055C7B00069B91 /* ASDimensionInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDimensionInternal.h; sourceTree = ""; }; 690ED58D1E36BCA6000627C0 /* ASLayoutElementStylePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutElementStylePrivate.h; sourceTree = ""; }; - 690ED5931E36D118000627C0 /* ASControlNode+tvOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ASControlNode+tvOS.m"; sourceTree = ""; }; - 690ED5951E36D118000627C0 /* ASImageNode+tvOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ASImageNode+tvOS.m"; sourceTree = ""; }; + 690ED5931E36D118000627C0 /* ASControlNode+tvOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASControlNode+tvOS.mm"; sourceTree = ""; }; + 690ED5951E36D118000627C0 /* ASImageNode+tvOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASImageNode+tvOS.mm"; sourceTree = ""; }; 692510131E74FB44003F2DD0 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 692BE8D61E36B65B00C86D87 /* ASLayoutSpecPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutSpecPrivate.h; sourceTree = ""; }; 6947B0BC1E36B4E30007C478 /* ASStackUnpositionedLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackUnpositionedLayout.h; sourceTree = ""; }; @@ -711,35 +720,35 @@ 696FCB301D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASBackgroundLayoutSpecSnapshotTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 6977965D1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASLayoutSpec+Subclasses.h"; sourceTree = ""; }; 6977965E1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASLayoutSpec+Subclasses.mm"; sourceTree = ""; }; - 697B31591CFE4B410049936F /* ASEditableTextNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASEditableTextNodeTests.m; sourceTree = ""; }; + 697B31591CFE4B410049936F /* ASEditableTextNodeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEditableTextNodeTests.mm; sourceTree = ""; }; 698371D91E4379CD00437585 /* ASNodeController+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASNodeController+Beta.h"; sourceTree = ""; }; 698371DA1E4379CD00437585 /* ASNodeController+Beta.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASNodeController+Beta.mm"; sourceTree = ""; }; 698C8B601CAB49FC0052DC3F /* ASLayoutElementExtensibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutElementExtensibility.h; sourceTree = ""; }; 698DFF431E36B6C9002891F1 /* ASStackLayoutSpecUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackLayoutSpecUtilities.h; sourceTree = ""; }; 698DFF461E36B7E9002891F1 /* ASLayoutSpecUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutSpecUtilities.h; sourceTree = ""; }; - 699B83501E3C1BA500433FA4 /* ASLayoutSpecTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutSpecTests.m; sourceTree = ""; }; + 699B83501E3C1BA500433FA4 /* ASLayoutSpecTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASLayoutSpecTests.mm; sourceTree = ""; }; 69B225661D72535E00B25B22 /* ASDisplayNodeLayoutTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeLayoutTests.mm; sourceTree = ""; }; 69BCE3D71EC6513B007DCCAD /* ASDisplayNode+Layout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASDisplayNode+Layout.mm"; 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 = ""; }; 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASRangeControllerUpdateRangeProtocol+Beta.h"; sourceTree = ""; }; - 69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutElementStyleTests.m; sourceTree = ""; }; + 69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASLayoutElementStyleTests.mm; sourceTree = ""; }; 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = ""; }; 764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AsyncDisplayKit+Debug.h"; sourceTree = ""; }; - 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AsyncDisplayKit+Debug.m"; sourceTree = ""; }; + 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "AsyncDisplayKit+Debug.mm"; sourceTree = ""; }; 7A06A7381C35F08800FE8DAA /* ASRelativeLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRelativeLayoutSpec.mm; sourceTree = ""; }; 7A06A7391C35F08800FE8DAA /* ASRelativeLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRelativeLayoutSpec.h; sourceTree = ""; }; 7AB338681C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRelativeLayoutSpecSnapshotTests.mm; sourceTree = ""; }; 8021EC1A1D2B00B100799119 /* UIImage+ASConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+ASConvenience.h"; sourceTree = ""; }; - 8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+ASConvenience.m"; sourceTree = ""; }; - 81E95C131D62639600336598 /* ASTextNodeSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextNodeSnapshotTests.m; sourceTree = ""; }; + 8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UIImage+ASConvenience.mm"; sourceTree = ""; }; + 81E95C131D62639600336598 /* ASTextNodeSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextNodeSnapshotTests.mm; sourceTree = ""; }; 81EE384D1C8E94F000456208 /* ASRunLoopQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASRunLoopQueue.h; path = ../ASRunLoopQueue.h; sourceTree = ""; }; 81EE384E1C8E94F000456208 /* ASRunLoopQueue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASRunLoopQueue.mm; path = ../ASRunLoopQueue.mm; sourceTree = ""; }; 83A7D9581D44542100BF333E /* ASWeakMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASWeakMap.h; sourceTree = ""; }; - 83A7D9591D44542100BF333E /* ASWeakMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakMap.m; sourceTree = ""; }; - 83A7D95D1D446A6E00BF333E /* ASWeakMapTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakMapTests.m; sourceTree = ""; }; + 83A7D9591D44542100BF333E /* ASWeakMap.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASWeakMap.mm; sourceTree = ""; }; + 83A7D95D1D446A6E00BF333E /* ASWeakMapTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASWeakMapTests.mm; sourceTree = ""; }; 8B0768B11CE752EC002E1453 /* ASDefaultPlaybackButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDefaultPlaybackButton.h; sourceTree = ""; }; - 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDefaultPlaybackButton.m; sourceTree = ""; }; + 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDefaultPlaybackButton.mm; sourceTree = ""; }; 8BDA5FC31CDBDDE1007D13B2 /* ASVideoPlayerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASVideoPlayerNode.h; sourceTree = ""; }; 8BDA5FC41CDBDDE1007D13B2 /* ASVideoPlayerNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASVideoPlayerNode.mm; sourceTree = ""; }; 9019FBBB1ED8061D00C45F72 /* ASYogaUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASYogaUtilities.h; sourceTree = ""; }; @@ -752,22 +761,22 @@ 92DD2FE51BF4D05E0074C9DD /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; 9C49C36E1B853957000B0DD5 /* ASStackLayoutElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackLayoutElement.h; sourceTree = ""; }; 9C5586671BD549CB00B50E3A /* ASAsciiArtBoxCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASAsciiArtBoxCreator.h; sourceTree = ""; }; - 9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASAsciiArtBoxCreator.m; sourceTree = ""; }; + 9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASAsciiArtBoxCreator.mm; sourceTree = ""; }; 9C6BB3B01B8CC9C200F13F52 /* ASAbsoluteLayoutElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASAbsoluteLayoutElement.h; sourceTree = ""; }; 9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTraitCollection.h; sourceTree = ""; }; - 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTraitCollection.m; sourceTree = ""; }; + 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTraitCollection.mm; sourceTree = ""; }; 9C8898BA1C738B9800D6B02E /* ASTextKitFontSizeAdjuster.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitFontSizeAdjuster.mm; path = TextKit/ASTextKitFontSizeAdjuster.mm; sourceTree = ""; }; 9CDC18CB1B910E12004965E2 /* ASLayoutElementPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutElementPrivate.h; 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.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASCollectionViewTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 9F98C0231DBDF2A300476D92 /* ASControlTargetAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASControlTargetAction.h; sourceTree = ""; }; - 9F98C0241DBDF2A300476D92 /* ASControlTargetAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASControlTargetAction.m; sourceTree = ""; }; + 9F98C0241DBDF2A300476D92 /* ASControlTargetAction.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASControlTargetAction.mm; sourceTree = ""; }; 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 = ""; }; + A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASPINRemoteImageDownloader.mm; path = Details/ASPINRemoteImageDownloader.mm; sourceTree = ""; }; A32FEDD31C501B6A004F642A /* ASTextKitFontSizeAdjuster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitFontSizeAdjuster.h; path = TextKit/ASTextKitFontSizeAdjuster.h; sourceTree = ""; }; A373200E1C571B050011FC94 /* ASTextNode+Beta.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ASTextNode+Beta.h"; sourceTree = ""; }; - AC026B571BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASAbsoluteLayoutSpecSnapshotTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + AC026B571BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASAbsoluteLayoutSpecSnapshotTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; AC026B6D1BD57DBF00BBC17E /* _ASHierarchyChangeSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASHierarchyChangeSet.h; sourceTree = ""; }; AC026B6E1BD57DBF00BBC17E /* _ASHierarchyChangeSet.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASHierarchyChangeSet.mm; sourceTree = ""; }; AC21EC0F1B3D0BF600C8B19A /* ASStackLayoutDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackLayoutDefines.h; sourceTree = ""; }; @@ -775,7 +784,7 @@ AC3C4A501A1139C100143C57 /* ASCollectionView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASCollectionView.mm; sourceTree = ""; }; AC3C4A531A113EEC00143C57 /* ASCollectionViewProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionViewProtocols.h; sourceTree = ""; }; AC6145401D8AFAE8003D62A2 /* ASSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASSection.h; path = ../Private/ASSection.h; sourceTree = ""; }; - AC6145421D8AFD4F003D62A2 /* ASSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASSection.m; path = ../Private/ASSection.m; sourceTree = ""; }; + AC6145421D8AFD4F003D62A2 /* ASSection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASSection.mm; path = ../Private/ASSection.mm; sourceTree = ""; }; 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 = ""; }; @@ -802,151 +811,159 @@ ACF6ED181B17843500DA7C62 /* ASAbsoluteLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASAbsoluteLayoutSpec.h; sourceTree = ""; }; ACF6ED191B17843500DA7C62 /* ASAbsoluteLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASAbsoluteLayoutSpec.mm; sourceTree = ""; }; ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASInternalHelpers.h; sourceTree = ""; }; - ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASInternalHelpers.m; sourceTree = ""; }; + ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASInternalHelpers.mm; sourceTree = ""; }; ACF6ED531B178DC700DA7C62 /* ASCenterLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASCenterLayoutSpecSnapshotTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; ACF6ED541B178DC700DA7C62 /* ASDimensionTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASDimensionTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; ACF6ED551B178DC700DA7C62 /* ASInsetLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASInsetLayoutSpecSnapshotTests.mm; sourceTree = ""; }; ACF6ED571B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutSpecSnapshotTestsHelper.h; sourceTree = ""; }; - ACF6ED581B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASLayoutSpecSnapshotTestsHelper.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + ACF6ED581B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASLayoutSpecSnapshotTestsHelper.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; ACF6ED591B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASOverlayLayoutSpecSnapshotTests.mm; sourceTree = ""; }; ACF6ED5A1B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRatioLayoutSpecSnapshotTests.mm; sourceTree = ""; }; ACF6ED5B1B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackLayoutSpecSnapshotTests.mm; sourceTree = ""; }; AE440174210FB7CF00B36DA2 /* ASTextKitFontSizeAdjusterTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextKitFontSizeAdjusterTests.mm; sourceTree = ""; }; - AE6987C01DD04E1000B9E458 /* ASPagerNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPagerNodeTests.m; sourceTree = ""; }; + AE6987C01DD04E1000B9E458 /* ASPagerNodeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPagerNodeTests.mm; sourceTree = ""; }; AEB7B0181C5962EA00662EF4 /* ASDefaultPlayButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDefaultPlayButton.h; sourceTree = ""; }; - AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDefaultPlayButton.m; sourceTree = ""; }; + AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDefaultPlayButton.mm; sourceTree = ""; }; AEEC47DF1C20C2DD00EC1693 /* ASVideoNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASVideoNode.h; sourceTree = ""; }; 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 = ""; }; + AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASVideoNodeTests.mm; sourceTree = ""; }; B0F880581BEAEC7500D17647 /* ASTableNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTableNode.h; 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 = ""; }; - B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASLayoutManager.m; path = TextKit/ASLayoutManager.m; sourceTree = ""; }; + B30BF6511C5964B0004FCD53 /* ASLayoutManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASLayoutManager.mm; path = TextKit/ASLayoutManager.mm; sourceTree = ""; }; B35061DA1B010EDF0018CF92 /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AsyncDisplayKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - BB5FC3CD1F9BA688007F191E /* ASNavigationControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASNavigationControllerTests.m; sourceTree = ""; }; - BB5FC3D01F9C9389007F191E /* ASTabBarControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASTabBarControllerTests.m; sourceTree = ""; }; + BB5FC3CD1F9BA688007F191E /* ASNavigationControllerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASNavigationControllerTests.mm; sourceTree = ""; }; + BB5FC3D01F9C9389007F191E /* ASTabBarControllerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTabBarControllerTests.mm; sourceTree = ""; }; BDC2D162BD55A807C1475DA5 /* Pods-AsyncDisplayKitTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.profile.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.profile.xcconfig"; sourceTree = ""; }; - C057D9BC20B5453D00FC9112 /* ASTextNode2SnapshotTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASTextNode2SnapshotTests.m; sourceTree = ""; }; + C018DF20216BF26600181FDA /* ASAbstractLayoutController+FrameworkPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASAbstractLayoutController+FrameworkPrivate.h"; sourceTree = ""; }; + C057D9BC20B5453D00FC9112 /* ASTextNode2SnapshotTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextNode2SnapshotTests.mm; sourceTree = ""; }; CC034A071E60BEB400626263 /* ASDisplayNode+Convenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+Convenience.h"; sourceTree = ""; }; - CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ASDisplayNode+Convenience.m"; sourceTree = ""; }; + CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASDisplayNode+Convenience.mm"; sourceTree = ""; }; CC034A111E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AsyncDisplayKit+IGListKitMethods.h"; sourceTree = ""; }; - CC034A121E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AsyncDisplayKit+IGListKitMethods.m"; sourceTree = ""; }; - CC051F1E1D7A286A006434CB /* ASCALayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCALayerTests.m; sourceTree = ""; }; - CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASUICollectionViewTests.m; sourceTree = ""; }; - CC0F88591E42807F00576FED /* ASCollectionViewFlowLayoutInspector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionViewFlowLayoutInspector.m; sourceTree = ""; }; + CC034A121E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "AsyncDisplayKit+IGListKitMethods.mm"; sourceTree = ""; }; + CC051F1E1D7A286A006434CB /* ASCALayerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCALayerTests.mm; sourceTree = ""; }; + CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASUICollectionViewTests.mm; sourceTree = ""; }; + CC0F88591E42807F00576FED /* ASCollectionViewFlowLayoutInspector.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionViewFlowLayoutInspector.mm; sourceTree = ""; }; CC0F885A1E42807F00576FED /* ASCollectionViewFlowLayoutInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionViewFlowLayoutInspector.h; sourceTree = ""; }; - CC0F885D1E4280B800576FED /* _ASCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _ASCollectionViewCell.m; sourceTree = ""; }; + CC0F885D1E4280B800576FED /* _ASCollectionViewCell.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASCollectionViewCell.mm; sourceTree = ""; }; CC0F885E1E4280B800576FED /* _ASCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASCollectionViewCell.h; sourceTree = ""; }; CC0F88691E4286FA00576FED /* ReferenceImages_64 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ReferenceImages_64; sourceTree = ""; }; CC0F886A1E4286FA00576FED /* ReferenceImages_iOS_10 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ReferenceImages_iOS_10; sourceTree = ""; }; - CC11F9791DB181180024D77B /* ASNetworkImageNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASNetworkImageNodeTests.m; sourceTree = ""; }; + CC11F9791DB181180024D77B /* ASNetworkImageNodeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASNetworkImageNodeTests.mm; sourceTree = ""; }; CC18248B200D49C800875940 /* ASTextNodeCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASTextNodeCommon.h; sourceTree = ""; }; CC224E952066CA6D00BBA57F /* configuration.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = configuration.json; sourceTree = ""; }; CC2E317F1DAC353700EEE891 /* ASCollectionView+Undeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionView+Undeprecated.h"; sourceTree = ""; }; CC2F65EC1E5FFB1600DA57C9 /* ASMutableElementMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMutableElementMap.h; sourceTree = ""; }; - CC2F65ED1E5FFB1600DA57C9 /* ASMutableElementMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASMutableElementMap.m; sourceTree = ""; }; + CC2F65ED1E5FFB1600DA57C9 /* ASMutableElementMap.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMutableElementMap.mm; sourceTree = ""; }; CC35CEC120DD7F600006448D /* ASCollections.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASCollections.h; sourceTree = ""; }; - CC35CEC220DD7F600006448D /* ASCollections.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASCollections.m; sourceTree = ""; }; - CC35CEC520DD87280006448D /* ASCollectionsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASCollectionsTests.m; sourceTree = ""; }; + CC35CEC220DD7F600006448D /* ASCollections.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollections.mm; sourceTree = ""; }; + CC35CEC520DD87280006448D /* ASCollectionsTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionsTests.mm; sourceTree = ""; }; + CC36C18E218B841600232F23 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + CC36C190218B841A00232F23 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; + CC36C192218B842E00232F23 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + CC36C195218B845B00232F23 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + CC36C197218B846300232F23 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + CC36C199218B846F00232F23 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; + CC36C19B218B847400232F23 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; CC3B20811C3F76D600798563 /* ASPendingStateController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPendingStateController.h; sourceTree = ""; }; CC3B20821C3F76D600798563 /* ASPendingStateController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPendingStateController.mm; sourceTree = ""; }; CC3B20871C3F7A5400798563 /* ASWeakSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASWeakSet.h; sourceTree = ""; }; - CC3B20881C3F7A5400798563 /* ASWeakSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakSet.m; sourceTree = ""; }; - CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakSetTests.m; sourceTree = ""; }; + CC3B20881C3F7A5400798563 /* ASWeakSet.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASWeakSet.mm; sourceTree = ""; }; + CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASWeakSetTests.mm; sourceTree = ""; }; CC3B208F1C3F892D00798563 /* ASBridgedPropertiesTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASBridgedPropertiesTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - CC4981B21D1A02BE004E13CC /* ASTableViewThrashTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableViewThrashTests.m; sourceTree = ""; }; + CC4981B21D1A02BE004E13CC /* ASTableViewThrashTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTableViewThrashTests.mm; sourceTree = ""; }; CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSIndexSet+ASHelpers.h"; sourceTree = ""; }; - CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSIndexSet+ASHelpers.m"; sourceTree = ""; }; + CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSIndexSet+ASHelpers.mm"; sourceTree = ""; }; CC4C2A751D88E3BF0039ACAB /* ASTraceEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTraceEvent.h; sourceTree = ""; }; - CC4C2A761D88E3BF0039ACAB /* ASTraceEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTraceEvent.m; sourceTree = ""; }; + CC4C2A761D88E3BF0039ACAB /* ASTraceEvent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTraceEvent.mm; sourceTree = ""; }; CC512B841DAC45C60054848E /* ASTableView+Undeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASTableView+Undeprecated.h"; sourceTree = ""; }; CC54A81B1D70077A00296A24 /* ASDispatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASDispatch.h; sourceTree = ""; }; - CC54A81D1D7008B300296A24 /* ASDispatchTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASDispatchTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + CC54A81D1D7008B300296A24 /* ASDispatchTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASDispatchTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; CC55A70B1E529FA200594372 /* UIResponder+AsyncDisplayKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIResponder+AsyncDisplayKit.h"; sourceTree = ""; }; - CC55A70C1E529FA200594372 /* UIResponder+AsyncDisplayKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIResponder+AsyncDisplayKit.m"; sourceTree = ""; }; + CC55A70C1E529FA200594372 /* UIResponder+AsyncDisplayKit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UIResponder+AsyncDisplayKit.mm"; sourceTree = ""; }; CC55A70F1E52A0F200594372 /* ASResponderChainEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASResponderChainEnumerator.h; sourceTree = ""; }; - CC55A7101E52A0F200594372 /* ASResponderChainEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASResponderChainEnumerator.m; sourceTree = ""; }; + CC55A7101E52A0F200594372 /* ASResponderChainEnumerator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASResponderChainEnumerator.mm; sourceTree = ""; }; CC5601391F06E9A700DC4FBE /* ASIntegerMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIntegerMap.h; sourceTree = ""; }; CC56013A1F06E9A700DC4FBE /* ASIntegerMap.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASIntegerMap.mm; sourceTree = ""; }; CC57EAF91E394EA40034C595 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CC583AC01EF9BAB400134156 /* ASDisplayNode+OCMock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "ASDisplayNode+OCMock.m"; sourceTree = ""; }; + CC583AC01EF9BAB400134156 /* ASDisplayNode+OCMock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASDisplayNode+OCMock.mm"; sourceTree = ""; }; CC583AC11EF9BAB400134156 /* ASTestCase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASTestCase.h; sourceTree = ""; }; - CC583AC21EF9BAB400134156 /* ASTestCase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASTestCase.m; sourceTree = ""; }; + CC583AC21EF9BAB400134156 /* ASTestCase.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTestCase.mm; sourceTree = ""; }; CC583AC31EF9BAB400134156 /* ASXCTExtensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASXCTExtensions.h; sourceTree = ""; }; CC583AC41EF9BAB400134156 /* NSInvocation+ASTestHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSInvocation+ASTestHelpers.h"; sourceTree = ""; }; - CC583AC51EF9BAB400134156 /* NSInvocation+ASTestHelpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSInvocation+ASTestHelpers.m"; sourceTree = ""; }; + CC583AC51EF9BAB400134156 /* NSInvocation+ASTestHelpers.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSInvocation+ASTestHelpers.mm"; sourceTree = ""; }; CC583AC61EF9BAB400134156 /* OCMockObject+ASAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OCMockObject+ASAdditions.h"; sourceTree = ""; }; - CC583AC71EF9BAB400134156 /* OCMockObject+ASAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OCMockObject+ASAdditions.m"; sourceTree = ""; }; + CC583AC71EF9BAB400134156 /* OCMockObject+ASAdditions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "OCMockObject+ASAdditions.mm"; sourceTree = ""; }; CC58AA4A1E398E1D002C8CB4 /* ASBlockTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASBlockTypes.h; sourceTree = ""; }; CC6AA2D81E9F03B900978E87 /* ASDisplayNode+Ancestry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ASDisplayNode+Ancestry.h"; path = "Base/ASDisplayNode+Ancestry.h"; sourceTree = ""; }; - CC6AA2D91E9F03B900978E87 /* ASDisplayNode+Ancestry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ASDisplayNode+Ancestry.m"; path = "Base/ASDisplayNode+Ancestry.m"; sourceTree = ""; }; + CC6AA2D91E9F03B900978E87 /* ASDisplayNode+Ancestry.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "ASDisplayNode+Ancestry.mm"; path = "Base/ASDisplayNode+Ancestry.mm"; sourceTree = ""; }; CC7AF195200D9BD500A21BDE /* ASExperimentalFeatures.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASExperimentalFeatures.h; sourceTree = ""; }; - CC7AF197200D9E8400A21BDE /* ASExperimentalFeatures.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASExperimentalFeatures.m; sourceTree = ""; }; + CC7AF197200D9E8400A21BDE /* ASExperimentalFeatures.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASExperimentalFeatures.mm; sourceTree = ""; }; CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPhotosFrameworkImageRequest.h; sourceTree = ""; }; - CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequest.m; sourceTree = ""; }; - CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequestTests.m; sourceTree = ""; }; + CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPhotosFrameworkImageRequest.mm; sourceTree = ""; }; + CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPhotosFrameworkImageRequestTests.mm; sourceTree = ""; }; CC84C7F020474C5300A3851B /* ASCGImageBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASCGImageBuffer.h; sourceTree = ""; }; - CC84C7F120474C5300A3851B /* ASCGImageBuffer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASCGImageBuffer.m; sourceTree = ""; }; + CC84C7F120474C5300A3851B /* ASCGImageBuffer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCGImageBuffer.mm; sourceTree = ""; }; CC87BB941DA8193C0090E380 /* ASCellNode+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCellNode+Internal.h"; sourceTree = ""; }; CC8B05D41D73836400F54286 /* ASPerformanceTestContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPerformanceTestContext.h; sourceTree = ""; }; - CC8B05D51D73836400F54286 /* ASPerformanceTestContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPerformanceTestContext.m; sourceTree = ""; }; - CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextNodePerformanceTests.m; sourceTree = ""; }; - CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASViewControllerTests.m; sourceTree = ""; }; + CC8B05D51D73836400F54286 /* ASPerformanceTestContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPerformanceTestContext.mm; sourceTree = ""; }; + CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextNodePerformanceTests.mm; sourceTree = ""; }; + CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASViewControllerTests.mm; sourceTree = ""; }; CCA282B21E9EA7310037E8B7 /* ASTipsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTipsController.h; sourceTree = ""; }; - CCA282B31E9EA7310037E8B7 /* ASTipsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTipsController.m; sourceTree = ""; }; + CCA282B31E9EA7310037E8B7 /* ASTipsController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTipsController.mm; sourceTree = ""; }; CCA282B61E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AsyncDisplayKit+Tips.h"; sourceTree = ""; }; - CCA282B71E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AsyncDisplayKit+Tips.m"; sourceTree = ""; }; + CCA282B71E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "AsyncDisplayKit+Tips.mm"; sourceTree = ""; }; CCA282BA1E9EABDD0037E8B7 /* ASTipProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTipProvider.h; sourceTree = ""; }; - CCA282BB1E9EABDD0037E8B7 /* ASTipProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTipProvider.m; sourceTree = ""; }; + CCA282BB1E9EABDD0037E8B7 /* ASTipProvider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTipProvider.mm; sourceTree = ""; }; CCA282BE1E9EAE010037E8B7 /* ASTip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTip.h; sourceTree = ""; }; - CCA282BF1E9EAE010037E8B7 /* ASTip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTip.m; sourceTree = ""; }; + CCA282BF1E9EAE010037E8B7 /* ASTip.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTip.mm; sourceTree = ""; }; CCA282C21E9EAE630037E8B7 /* ASLayerBackingTipProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayerBackingTipProvider.h; sourceTree = ""; }; - CCA282C31E9EAE630037E8B7 /* ASLayerBackingTipProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayerBackingTipProvider.m; sourceTree = ""; }; + CCA282C31E9EAE630037E8B7 /* ASLayerBackingTipProvider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASLayerBackingTipProvider.mm; sourceTree = ""; }; CCA282C61E9EB64B0037E8B7 /* ASDisplayNodeTipState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeTipState.h; sourceTree = ""; }; - CCA282C71E9EB64B0037E8B7 /* ASDisplayNodeTipState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDisplayNodeTipState.m; sourceTree = ""; }; + CCA282C71E9EB64B0037E8B7 /* ASDisplayNodeTipState.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeTipState.mm; sourceTree = ""; }; CCA282CA1E9EB73E0037E8B7 /* ASTipNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTipNode.h; sourceTree = ""; }; - CCA282CB1E9EB73E0037E8B7 /* ASTipNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTipNode.m; sourceTree = ""; }; + CCA282CB1E9EB73E0037E8B7 /* ASTipNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTipNode.mm; sourceTree = ""; }; CCA282CE1E9EBF6C0037E8B7 /* ASTipsWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTipsWindow.h; sourceTree = ""; }; - CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTipsWindow.m; sourceTree = ""; }; - CCA5F62D1EECC2A80060C137 /* ASAssert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASAssert.m; sourceTree = ""; }; + CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTipsWindow.mm; sourceTree = ""; }; + CCA5F62D1EECC2A80060C137 /* ASAssert.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASAssert.mm; sourceTree = ""; }; CCAA0B7D206ADBF30057B336 /* ASRecursiveUnfairLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASRecursiveUnfairLock.h; sourceTree = ""; }; - CCAA0B7E206ADBF30057B336 /* ASRecursiveUnfairLock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASRecursiveUnfairLock.m; sourceTree = ""; }; - CCAA0B81206ADECB0057B336 /* ASRecursiveUnfairLockTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASRecursiveUnfairLockTests.m; sourceTree = ""; }; - CCB1F9591EFB60A5009C7475 /* ASLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLog.m; sourceTree = ""; }; + CCAA0B7E206ADBF30057B336 /* ASRecursiveUnfairLock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRecursiveUnfairLock.mm; sourceTree = ""; }; + CCAA0B81206ADECB0057B336 /* ASRecursiveUnfairLockTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRecursiveUnfairLockTests.mm; sourceTree = ""; }; + CCB1F9591EFB60A5009C7475 /* ASLog.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASLog.mm; sourceTree = ""; }; CCB1F95B1EFB6316009C7475 /* ASSignpost.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASSignpost.h; sourceTree = ""; }; - CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDisplayNodeSnapshotTests.m; sourceTree = ""; }; + CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeSnapshotTests.mm; sourceTree = ""; }; CCBBBF5C1EB161760069AA91 /* ASRangeManagingNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRangeManagingNode.h; sourceTree = ""; }; - CCBD05DE1E4147B000D18509 /* ASIGListAdapterBasedDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIGListAdapterBasedDataSource.m; sourceTree = ""; }; + CCBD05DE1E4147B000D18509 /* ASIGListAdapterBasedDataSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASIGListAdapterBasedDataSource.mm; sourceTree = ""; }; CCBD05DF1E4147B000D18509 /* ASIGListAdapterBasedDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIGListAdapterBasedDataSource.h; sourceTree = ""; }; CCBDDD0320C62A2D00CBA922 /* ASMainThreadDeallocation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASMainThreadDeallocation.h; sourceTree = ""; }; CCBDDD0420C62A2D00CBA922 /* ASMainThreadDeallocation.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMainThreadDeallocation.mm; sourceTree = ""; }; CCCCCCC31EC3EF060087FE10 /* ASTextDebugOption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTextDebugOption.h; sourceTree = ""; }; - CCCCCCC41EC3EF060087FE10 /* ASTextDebugOption.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextDebugOption.m; sourceTree = ""; }; + CCCCCCC41EC3EF060087FE10 /* ASTextDebugOption.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextDebugOption.mm; sourceTree = ""; }; CCCCCCC51EC3EF060087FE10 /* ASTextInput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTextInput.h; sourceTree = ""; }; - CCCCCCC61EC3EF060087FE10 /* ASTextInput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextInput.m; sourceTree = ""; }; + CCCCCCC61EC3EF060087FE10 /* ASTextInput.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextInput.mm; sourceTree = ""; }; CCCCCCC71EC3EF060087FE10 /* ASTextLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTextLayout.h; sourceTree = ""; }; - CCCCCCC81EC3EF060087FE10 /* ASTextLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextLayout.m; sourceTree = ""; }; + CCCCCCC81EC3EF060087FE10 /* ASTextLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextLayout.mm; sourceTree = ""; }; CCCCCCC91EC3EF060087FE10 /* ASTextLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTextLine.h; sourceTree = ""; }; - CCCCCCCA1EC3EF060087FE10 /* ASTextLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextLine.m; sourceTree = ""; }; + CCCCCCCA1EC3EF060087FE10 /* ASTextLine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextLine.mm; sourceTree = ""; }; CCCCCCCC1EC3EF060087FE10 /* ASTextAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTextAttribute.h; sourceTree = ""; }; - CCCCCCCD1EC3EF060087FE10 /* ASTextAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextAttribute.m; sourceTree = ""; }; + CCCCCCCD1EC3EF060087FE10 /* ASTextAttribute.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextAttribute.mm; sourceTree = ""; }; CCCCCCCE1EC3EF060087FE10 /* ASTextRunDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTextRunDelegate.h; sourceTree = ""; }; - CCCCCCCF1EC3EF060087FE10 /* ASTextRunDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextRunDelegate.m; sourceTree = ""; }; + CCCCCCCF1EC3EF060087FE10 /* ASTextRunDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextRunDelegate.mm; sourceTree = ""; }; CCCCCCD11EC3EF060087FE10 /* ASTextUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTextUtilities.h; sourceTree = ""; }; - CCCCCCD21EC3EF060087FE10 /* ASTextUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextUtilities.m; sourceTree = ""; }; + CCCCCCD21EC3EF060087FE10 /* ASTextUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextUtilities.mm; sourceTree = ""; }; CCCCCCD31EC3EF060087FE10 /* NSParagraphStyle+ASText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSParagraphStyle+ASText.h"; sourceTree = ""; }; - CCCCCCD41EC3EF060087FE10 /* NSParagraphStyle+ASText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSParagraphStyle+ASText.m"; sourceTree = ""; }; + CCCCCCD41EC3EF060087FE10 /* NSParagraphStyle+ASText.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSParagraphStyle+ASText.mm"; sourceTree = ""; }; CCCCCCE51EC3F0FC0087FE10 /* NSAttributedString+ASText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSAttributedString+ASText.h"; sourceTree = ""; }; - CCCCCCE61EC3F0FC0087FE10 /* NSAttributedString+ASText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSAttributedString+ASText.m"; sourceTree = ""; }; + CCCCCCE61EC3F0FC0087FE10 /* NSAttributedString+ASText.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSAttributedString+ASText.mm"; sourceTree = ""; }; CCDC9B4B200991D10063C1F8 /* ASGraphicsContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASGraphicsContext.h; sourceTree = ""; }; - CCDC9B4C200991D10063C1F8 /* ASGraphicsContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASGraphicsContext.m; sourceTree = ""; }; - CCDD148A1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionModernDataSourceTests.m; sourceTree = ""; }; + CCDC9B4C200991D10063C1F8 /* ASGraphicsContext.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASGraphicsContext.mm; sourceTree = ""; }; + CCDD148A1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionModernDataSourceTests.mm; sourceTree = ""; }; CCE04B1E1E313EA7006AEBBB /* ASSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASSectionController.h; sourceTree = ""; }; CCE04B201E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IGListAdapter+AsyncDisplayKit.h"; sourceTree = ""; }; - CCE04B211E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "IGListAdapter+AsyncDisplayKit.m"; sourceTree = ""; }; + CCE04B211E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "IGListAdapter+AsyncDisplayKit.mm"; sourceTree = ""; }; CCE04B2B1E314A32006AEBBB /* ASSupplementaryNodeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASSupplementaryNodeSource.h; sourceTree = ""; }; - CCE4F9B21F0D60AC00062E4E /* ASIntegerMapTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIntegerMapTests.m; sourceTree = ""; }; + CCE4F9B21F0D60AC00062E4E /* ASIntegerMapTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASIntegerMapTests.mm; sourceTree = ""; }; CCE4F9B41F0DA4F300062E4E /* ASLayoutEngineTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASLayoutEngineTests.mm; sourceTree = ""; }; CCE4F9B61F0DBA5000062E4E /* ASLayoutTestNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutTestNode.h; sourceTree = ""; }; CCE4F9B71F0DBA5000062E4E /* ASLayoutTestNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASLayoutTestNode.mm; sourceTree = ""; }; @@ -954,43 +971,42 @@ CCE4F9BC1F0ECE5200062E4E /* ASTLayoutFixture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTLayoutFixture.h; sourceTree = ""; }; CCE4F9BD1F0ECE5200062E4E /* ASTLayoutFixture.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTLayoutFixture.mm; sourceTree = ""; }; CCED5E3C2020D36800395C40 /* ASNetworkImageLoadInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASNetworkImageLoadInfo.h; sourceTree = ""; }; - CCED5E3D2020D36800395C40 /* ASNetworkImageLoadInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASNetworkImageLoadInfo.m; sourceTree = ""; }; + CCED5E3D2020D36800395C40 /* ASNetworkImageLoadInfo.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASNetworkImageLoadInfo.mm; sourceTree = ""; }; CCED5E402020D41600395C40 /* ASNetworkImageLoadInfo+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ASNetworkImageLoadInfo+Private.h"; sourceTree = ""; }; CCEDDDC8200C2AC300FFCD0A /* ASConfigurationInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASConfigurationInternal.h; sourceTree = ""; }; - CCEDDDC9200C2AC300FFCD0A /* ASConfigurationInternal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASConfigurationInternal.m; sourceTree = ""; }; + CCEDDDC9200C2AC300FFCD0A /* ASConfigurationInternal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASConfigurationInternal.mm; sourceTree = ""; }; CCEDDDCC200C2CB900FFCD0A /* ASConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASConfiguration.h; sourceTree = ""; }; CCEDDDCE200C42A200FFCD0A /* ASConfigurationDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASConfigurationDelegate.h; sourceTree = ""; }; - CCEDDDD0200C488000FFCD0A /* ASConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASConfiguration.m; sourceTree = ""; }; - CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASConfigurationTests.m; sourceTree = ""; }; + CCEDDDD0200C488000FFCD0A /* ASConfiguration.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASConfiguration.mm; sourceTree = ""; }; + CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASConfigurationTests.mm; sourceTree = ""; }; CCF1FF5D20C4785000AAD8FC /* ASLocking.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASLocking.h; sourceTree = ""; }; D3779BCFF841AD3EB56537ED /* Pods-AsyncDisplayKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.release.xcconfig"; sourceTree = ""; }; D785F6601A74327E00291744 /* ASScrollNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASScrollNode.h; sourceTree = ""; }; D785F6611A74327E00291744 /* ASScrollNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASScrollNode.mm; sourceTree = ""; }; DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = _ASTransitionContext.h; path = ../_ASTransitionContext.h; sourceTree = ""; }; - DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = _ASTransitionContext.m; path = ../_ASTransitionContext.m; sourceTree = ""; }; + DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = _ASTransitionContext.mm; path = ../_ASTransitionContext.mm; sourceTree = ""; }; DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASContextTransitioning.h; sourceTree = ""; }; DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Diffing.h"; sourceTree = ""; }; DBC452DA1C5BF64600B16017 /* NSArray+Diffing.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSArray+Diffing.mm"; sourceTree = ""; }; - DBC452DD1C5C6A6A00B16017 /* ArrayDiffingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ArrayDiffingTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASDisplayNodeImplicitHierarchyTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + DBC452DD1C5C6A6A00B16017 /* ArrayDiffingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ArrayDiffingTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASDisplayNodeImplicitHierarchyTests.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; DBDB83921C6E879900D0098C /* ASPagerFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPagerFlowLayout.h; sourceTree = ""; }; - DBDB83931C6E879900D0098C /* ASPagerFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPagerFlowLayout.m; sourceTree = ""; }; + DBDB83931C6E879900D0098C /* ASPagerFlowLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPagerFlowLayout.mm; sourceTree = ""; }; DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+FrameworkPrivate.h"; sourceTree = ""; }; DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDelegateProxy.h; sourceTree = ""; }; - DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDelegateProxy.m; sourceTree = ""; }; + DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDelegateProxy.mm; sourceTree = ""; }; DEC146B41C37A16A004A0EE7 /* ASCollectionInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASCollectionInternal.h; path = Details/ASCollectionInternal.h; sourceTree = ""; }; - DEC146B51C37A16A004A0EE7 /* ASCollectionInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASCollectionInternal.m; path = Details/ASCollectionInternal.m; sourceTree = ""; }; DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASButtonNode.h; sourceTree = ""; }; DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASButtonNode.mm; sourceTree = ""; }; - E51B78BD1F01A0EE00E32604 /* ASLayoutFlatteningTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutFlatteningTests.m; sourceTree = ""; }; + E51B78BD1F01A0EE00E32604 /* ASLayoutFlatteningTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASLayoutFlatteningTests.mm; sourceTree = ""; }; E52405B21C8FEF03004DC8E7 /* ASLayoutTransition.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASLayoutTransition.mm; sourceTree = ""; }; E52405B41C8FEF16004DC8E7 /* ASLayoutTransition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutTransition.h; sourceTree = ""; }; E54E00711F1D3828000B30D7 /* ASPagerNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASPagerNode+Beta.h"; sourceTree = ""; }; E54E81FA1EB357BD00FFE8E1 /* ASPageTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPageTable.h; sourceTree = ""; }; - E54E81FB1EB357BD00FFE8E1 /* ASPageTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPageTable.m; sourceTree = ""; }; + E54E81FB1EB357BD00FFE8E1 /* ASPageTable.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPageTable.mm; sourceTree = ""; }; E55D86311CA8A14000A0C26F /* ASLayoutElement.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASLayoutElement.mm; sourceTree = ""; }; E5667E8B1F33871300FA6FC0 /* _ASCollectionGalleryLayoutInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASCollectionGalleryLayoutInfo.h; sourceTree = ""; }; - E5667E8D1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _ASCollectionGalleryLayoutInfo.m; sourceTree = ""; }; + E5667E8D1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASCollectionGalleryLayoutInfo.mm; sourceTree = ""; }; E5711A2A1C840C81009619D4 /* ASCollectionElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionElement.h; sourceTree = ""; }; E5711A2D1C840C96009619D4 /* ASCollectionElement.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionElement.mm; sourceTree = ""; }; E5775AFB1F13CE9F00CAC9BC /* _ASCollectionGalleryLayoutItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASCollectionGalleryLayoutItem.h; sourceTree = ""; }; @@ -998,21 +1014,21 @@ E5775AFF1F13D25400CAC9BC /* ASCollectionLayoutState+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionLayoutState+Private.h"; sourceTree = ""; }; E5775B011F16759300CAC9BC /* ASCollectionLayoutCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionLayoutCache.h; sourceTree = ""; }; E5775B031F16759F00CAC9BC /* ASCollectionLayoutCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionLayoutCache.mm; sourceTree = ""; }; - E5855DED1EBB4D83003639AE /* ASCollectionLayoutDefines.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionLayoutDefines.m; sourceTree = ""; }; + E5855DED1EBB4D83003639AE /* ASCollectionLayoutDefines.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionLayoutDefines.mm; sourceTree = ""; }; E5855DEE1EBB4D83003639AE /* ASCollectionLayoutDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionLayoutDefines.h; sourceTree = ""; }; - E586F96B1F9F9E2900ECE00E /* ASScrollNodeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASScrollNodeTests.m; sourceTree = ""; }; + E586F96B1F9F9E2900ECE00E /* ASScrollNodeTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASScrollNodeTests.mm; sourceTree = ""; }; E58E9E3D1E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionFlowLayoutDelegate.h; sourceTree = ""; }; - E58E9E3E1E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionFlowLayoutDelegate.m; sourceTree = ""; }; + E58E9E3E1E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionFlowLayoutDelegate.mm; sourceTree = ""; }; E58E9E3F1E941D74004CFC59 /* ASCollectionLayoutContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionLayoutContext.h; sourceTree = ""; }; - E58E9E401E941D74004CFC59 /* ASCollectionLayoutContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionLayoutContext.m; sourceTree = ""; }; + E58E9E401E941D74004CFC59 /* ASCollectionLayoutContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionLayoutContext.mm; sourceTree = ""; }; E58E9E411E941D74004CFC59 /* ASCollectionLayoutDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionLayoutDelegate.h; sourceTree = ""; }; E58E9E471E941DA5004CFC59 /* ASCollectionLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionLayout.h; sourceTree = ""; }; E58E9E481E941DA5004CFC59 /* ASCollectionLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASCollectionLayout.mm; sourceTree = ""; }; E5B077FD1E69F4EB00C24B5B /* ASElementMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASElementMap.h; sourceTree = ""; }; - E5B077FE1E69F4EB00C24B5B /* ASElementMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASElementMap.m; sourceTree = ""; }; - E5B225261F1790B5001E1431 /* ASHashing.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASHashing.m; sourceTree = ""; }; + E5B077FE1E69F4EB00C24B5B /* ASElementMap.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASElementMap.mm; sourceTree = ""; }; + E5B225261F1790B5001E1431 /* ASHashing.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASHashing.mm; sourceTree = ""; }; E5B225271F1790B5001E1431 /* ASHashing.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASHashing.h; sourceTree = ""; }; - E5B2252D1F17E521001E1431 /* ASDispatch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASDispatch.m; sourceTree = ""; }; + E5B2252D1F17E521001E1431 /* ASDispatch.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDispatch.mm; sourceTree = ""; }; E5B5B9D01E9BAD9800A6B726 /* ASCollectionLayoutContext+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionLayoutContext+Private.h"; sourceTree = ""; }; E5C347B01ECB3D9200EC4BE4 /* ASBatchFetchingDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASBatchFetchingDelegate.h; sourceTree = ""; }; E5C347B21ECB40AA00EC4BE4 /* ASTableNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASTableNode+Beta.h"; sourceTree = ""; }; @@ -1021,8 +1037,10 @@ E5E2D72D1EA780C4005C24C6 /* ASCollectionGalleryLayoutDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionGalleryLayoutDelegate.h; sourceTree = ""; }; E5E2D72F1EA780DF005C24C6 /* ASCollectionGalleryLayoutDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASCollectionGalleryLayoutDelegate.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AsyncDisplayKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + F325E48B21745F9E00AC93A4 /* ASButtonNodeTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASButtonNodeTests.mm; sourceTree = ""; }; + F325E48F217460B000AC93A4 /* ASTextNode2Tests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextNode2Tests.mm; sourceTree = ""; }; F3F698D1211CAD4600800CB1 /* ASDisplayViewAccessibilityTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayViewAccessibilityTests.mm; sourceTree = ""; }; - F711994D1D20C21100568860 /* ASDisplayNodeExtrasTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDisplayNodeExtrasTests.m; sourceTree = ""; }; + F711994D1D20C21100568860 /* ASDisplayNodeExtrasTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeExtrasTests.mm; sourceTree = ""; }; FA4FAF14200A850200E735BD /* ASControlNode+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASControlNode+Private.h"; sourceTree = ""; }; FB07EABBCF28656C6297BC2D /* Pods-AsyncDisplayKitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1032,6 +1050,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CC36C19D218B849C00232F23 /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1039,6 +1058,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CC36C19F218B894800232F23 /* CoreMedia.framework in Frameworks */, + CC36C19E218B894400232F23 /* AVFoundation.framework in Frameworks */, CC90E1F41E383C0400FED591 /* AsyncDisplayKit.framework in Frameworks */, 058D09BE195D04C000B7D73C /* XCTest.framework in Frameworks */, 058D09C1195D04C000B7D73C /* UIKit.framework in Frameworks */, @@ -1051,6 +1072,14 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CC36C19C218B847400232F23 /* CoreMedia.framework in Frameworks */, + CC36C19A218B846F00232F23 /* CoreLocation.framework in Frameworks */, + CC36C198218B846300232F23 /* QuartzCore.framework in Frameworks */, + CC36C196218B845B00232F23 /* AVFoundation.framework in Frameworks */, + CC36C194218B844800232F23 /* Foundation.framework in Frameworks */, + CC36C193218B842E00232F23 /* CoreGraphics.framework in Frameworks */, + CC36C191218B841A00232F23 /* CoreText.framework in Frameworks */, + CC36C18F218B841600232F23 /* UIKit.framework in Frameworks */, 92DD2FE61BF4D05E0074C9DD /* MapKit.framework in Frameworks */, B350625E1B0111780018CF92 /* AssetsLibrary.framework in Frameworks */, B350625D1B0111740018CF92 /* Photos.framework in Frameworks */, @@ -1064,7 +1093,7 @@ isa = PBXGroup; children = ( 057D02C51AC0A66700C7AC3C /* AppDelegate.h */, - 057D02C61AC0A66700C7AC3C /* AppDelegate.m */, + 057D02C61AC0A66700C7AC3C /* AppDelegate.mm */, 057D02C11AC0A66700C7AC3C /* Supporting Files */, ); name = AsyncDisplayKitTestHost; @@ -1076,7 +1105,7 @@ children = ( 692510131E74FB44003F2DD0 /* Default-568h@2x.png */, 057D02C21AC0A66700C7AC3C /* Info.plist */, - 057D02C31AC0A66700C7AC3C /* main.m */, + 057D02C31AC0A66700C7AC3C /* main.mm */, ); name = "Supporting Files"; sourceTree = ""; @@ -1109,6 +1138,13 @@ 058D09AE195D04C000B7D73C /* Frameworks */ = { isa = PBXGroup; children = ( + CC36C19B218B847400232F23 /* CoreMedia.framework */, + CC36C199218B846F00232F23 /* CoreLocation.framework */, + CC36C197218B846300232F23 /* QuartzCore.framework */, + CC36C195218B845B00232F23 /* AVFoundation.framework */, + CC36C192218B842E00232F23 /* CoreGraphics.framework */, + CC36C190218B841A00232F23 /* CoreText.framework */, + CC36C18E218B841600232F23 /* UIKit.framework */, 92DD2FE51BF4D05E0074C9DD /* MapKit.framework */, 051943141A1575670030A7D0 /* Photos.framework */, 051943121A1575630030A7D0 /* AssetsLibrary.framework */, @@ -1124,7 +1160,7 @@ isa = PBXGroup; children = ( CC35CEC120DD7F600006448D /* ASCollections.h */, - CC35CEC220DD7F600006448D /* ASCollections.m */, + CC35CEC220DD7F600006448D /* ASCollections.mm */, 058D0A42195D058D00B7D73C /* Base */, CCE04B1D1E313E99006AEBBB /* Collection Data Adapter */, DE89C1691DCEB9CC00D49D74 /* Debug */, @@ -1138,16 +1174,15 @@ DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */, DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */, CCEDDDCC200C2CB900FFCD0A /* ASConfiguration.h */, - CCEDDDD0200C488000FFCD0A /* ASConfiguration.m */, + CCEDDDD0200C488000FFCD0A /* ASConfiguration.mm */, CCEDDDC8200C2AC300FFCD0A /* ASConfigurationInternal.h */, - CCEDDDC9200C2AC300FFCD0A /* ASConfigurationInternal.m */, + CCEDDDC9200C2AC300FFCD0A /* ASConfigurationInternal.mm */, CCEDDDCE200C42A200FFCD0A /* ASConfigurationDelegate.h */, 055F1A3A19ABD43F004DAFF1 /* ASCellNode.h */, AC6456071B0A335000CF11B8 /* ASCellNode.mm */, CC84C7F020474C5300A3851B /* ASCGImageBuffer.h */, - CC84C7F120474C5300A3851B /* ASCGImageBuffer.m */, + CC84C7F120474C5300A3851B /* ASCGImageBuffer.mm */, DEC146B41C37A16A004A0EE7 /* ASCollectionInternal.h */, - DEC146B51C37A16A004A0EE7 /* ASCollectionInternal.m */, 18C2ED7C1B9B7DE800F627B3 /* ASCollectionNode.h */, 18C2ED7D1B9B7DE800F627B3 /* ASCollectionNode.mm */, B13CA0FF1C52004900E031AB /* ASCollectionNode+Beta.h */, @@ -1162,10 +1197,10 @@ 058D09D8195D050800B7D73C /* ASDisplayNode.h */, 058D09D9195D050800B7D73C /* ASDisplayNode.mm */, CC6AA2D81E9F03B900978E87 /* ASDisplayNode+Ancestry.h */, - CC6AA2D91E9F03B900978E87 /* ASDisplayNode+Ancestry.m */, + CC6AA2D91E9F03B900978E87 /* ASDisplayNode+Ancestry.mm */, 68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */, CC034A071E60BEB400626263 /* ASDisplayNode+Convenience.h */, - CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.m */, + CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.mm */, 683F563620E409D600CEB7A3 /* ASDisplayNode+InterfaceState.h */, 69BCE3D71EC6513B007DCCAD /* ASDisplayNode+Layout.mm */, 058D09DA195D050800B7D73C /* ASDisplayNode+Subclasses.h */, @@ -1175,7 +1210,7 @@ 0587F9BB1A7309ED00AFF0BA /* ASEditableTextNode.h */, 0587F9BC1A7309ED00AFF0BA /* ASEditableTextNode.mm */, CC7AF195200D9BD500A21BDE /* ASExperimentalFeatures.h */, - CC7AF197200D9E8400A21BDE /* ASExperimentalFeatures.m */, + CC7AF197200D9E8400A21BDE /* ASExperimentalFeatures.mm */, 058D09DD195D050800B7D73C /* ASImageNode.h */, 058D09DE195D050800B7D73C /* ASImageNode.mm */, 68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */, @@ -1187,26 +1222,26 @@ 0516FA3E1A1563D200B4EBED /* ASMultiplexImageNode.h */, 0516FA3F1A1563D200B4EBED /* ASMultiplexImageNode.mm */, 68FC85DC1CE29AB700EDD713 /* ASNavigationController.h */, - 68FC85DD1CE29AB700EDD713 /* ASNavigationController.m */, + 68FC85DD1CE29AB700EDD713 /* ASNavigationController.mm */, CCED5E3C2020D36800395C40 /* ASNetworkImageLoadInfo.h */, - CCED5E3D2020D36800395C40 /* ASNetworkImageLoadInfo.m */, + CCED5E3D2020D36800395C40 /* ASNetworkImageLoadInfo.mm */, 055B9FA61A1C154B00035D6D /* ASNetworkImageNode.h */, 055B9FA71A1C154B00035D6D /* ASNetworkImageNode.mm */, 698371D91E4379CD00437585 /* ASNodeController+Beta.h */, 698371DA1E4379CD00437585 /* ASNodeController+Beta.mm */, DBDB83921C6E879900D0098C /* ASPagerFlowLayout.h */, - DBDB83931C6E879900D0098C /* ASPagerFlowLayout.m */, + DBDB83931C6E879900D0098C /* ASPagerFlowLayout.mm */, 25E327541C16819500A2170C /* ASPagerNode.h */, - 25E327551C16819500A2170C /* ASPagerNode.m */, + 25E327551C16819500A2170C /* ASPagerNode.mm */, E54E00711F1D3828000B30D7 /* ASPagerNode+Beta.h */, A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */, - A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.m */, + A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.mm */, CCBBBF5C1EB161760069AA91 /* ASRangeManagingNode.h */, D785F6601A74327E00291744 /* ASScrollNode.h */, D785F6611A74327E00291744 /* ASScrollNode.mm */, ACE87A2B1D73696800D7FF06 /* ASSectionContext.h */, 68FC85E01CE29B7E00EDD713 /* ASTabBarController.h */, - 68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */, + 68FC85E11CE29B7E00EDD713 /* ASTabBarController.mm */, B0F880581BEAEC7500D17647 /* ASTableNode.h */, 9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */, E5C347B21ECB40AA00EC4BE4 /* ASTableNode+Beta.h */, @@ -1227,12 +1262,12 @@ ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */, 9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */, 68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */, - 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */, + 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.mm */, 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */, 8021EC1A1D2B00B100799119 /* UIImage+ASConvenience.h */, - 8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.m */, + 8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.mm */, CC55A70B1E529FA200594372 /* UIResponder+AsyncDisplayKit.h */, - CC55A70C1E529FA200594372 /* UIResponder+AsyncDisplayKit.m */, + CC55A70C1E529FA200594372 /* UIResponder+AsyncDisplayKit.mm */, ); path = Source; sourceTree = ""; @@ -1249,83 +1284,84 @@ 058D09C5195D04C000B7D73C /* Tests */ = { isa = PBXGroup; children = ( + F325E48F217460B000AC93A4 /* ASTextNode2Tests.mm */, + F325E48B21745F9E00AC93A4 /* ASButtonNodeTests.mm */, F3F698D1211CAD4600800CB1 /* ASDisplayViewAccessibilityTests.mm */, - DBC452DD1C5C6A6A00B16017 /* ArrayDiffingTests.m */, - AC026B571BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.m */, + DBC452DD1C5C6A6A00B16017 /* ArrayDiffingTests.mm */, + AC026B571BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.mm */, 696FCB301D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm */, - 29CDC2E11AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.m */, - 242995D21B29743C00090100 /* ASBasicImageDownloaderTests.m */, - 296A0A341A951ABF005ACEAA /* ASBatchFetchingTests.m */, + 29CDC2E11AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.mm */, + 242995D21B29743C00090100 /* ASBasicImageDownloaderTests.mm */, + 296A0A341A951ABF005ACEAA /* ASBatchFetchingTests.mm */, CC3B208F1C3F892D00798563 /* ASBridgedPropertiesTests.mm */, - CC051F1E1D7A286A006434CB /* ASCALayerTests.m */, + CC051F1E1D7A286A006434CB /* ASCALayerTests.mm */, ACF6ED531B178DC700DA7C62 /* ASCenterLayoutSpecSnapshotTests.mm */, - CCDD148A1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.m */, - CC35CEC520DD87280006448D /* ASCollectionsTests.m */, - 2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */, + CCDD148A1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.mm */, + CC35CEC520DD87280006448D /* ASCollectionsTests.mm */, + 2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.mm */, 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.mm */, - CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.m */, - 2911485B1A77147A005D0878 /* ASControlNodeTests.m */, + CCEDDDD8200C518800FFCD0A /* ASConfigurationTests.mm */, + 2911485B1A77147A005D0878 /* ASControlNodeTests.mm */, 1A6C000F1FAB4ED400D05926 /* ASCornerLayoutSpecSnapshotTests.mm */, ACF6ED541B178DC700DA7C62 /* ASDimensionTests.mm */, - CC54A81D1D7008B300296A24 /* ASDispatchTests.m */, - 058D0A2D195D057000B7D73C /* ASDisplayLayerTests.m */, - 058D0A2E195D057000B7D73C /* ASDisplayNodeAppearanceTests.m */, - F711994D1D20C21100568860 /* ASDisplayNodeExtrasTests.m */, - DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.m */, + CC54A81D1D7008B300296A24 /* ASDispatchTests.mm */, + 058D0A2D195D057000B7D73C /* ASDisplayLayerTests.mm */, + 058D0A2E195D057000B7D73C /* ASDisplayNodeAppearanceTests.mm */, + F711994D1D20C21100568860 /* ASDisplayNodeExtrasTests.mm */, + DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.mm */, 69B225661D72535E00B25B22 /* ASDisplayNodeLayoutTests.mm */, - CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */, + CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.mm */, 058D0A2F195D057000B7D73C /* ASDisplayNodeTests.mm */, 058D0A30195D057000B7D73C /* ASDisplayNodeTestsHelper.h */, - 058D0A31195D057000B7D73C /* ASDisplayNodeTestsHelper.m */, - 697B31591CFE4B410049936F /* ASEditableTextNodeTests.m */, - 056D21541ABCEF50001107EF /* ASImageNodeSnapshotTests.m */, + 058D0A31195D057000B7D73C /* ASDisplayNodeTestsHelper.mm */, + 697B31591CFE4B410049936F /* ASEditableTextNodeTests.mm */, + 056D21541ABCEF50001107EF /* ASImageNodeSnapshotTests.mm */, ACF6ED551B178DC700DA7C62 /* ASInsetLayoutSpecSnapshotTests.mm */, - CCE4F9B21F0D60AC00062E4E /* ASIntegerMapTests.m */, - 69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.m */, + CCE4F9B21F0D60AC00062E4E /* ASIntegerMapTests.mm */, + 69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.mm */, CCE4F9B41F0DA4F300062E4E /* ASLayoutEngineTests.mm */, - E51B78BD1F01A0EE00E32604 /* ASLayoutFlatteningTests.m */, + E51B78BD1F01A0EE00E32604 /* ASLayoutFlatteningTests.mm */, ACF6ED571B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.h */, - ACF6ED581B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.m */, - 699B83501E3C1BA500433FA4 /* ASLayoutSpecTests.m */, + ACF6ED581B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.mm */, + 699B83501E3C1BA500433FA4 /* ASLayoutSpecTests.mm */, CCE4F9B61F0DBA5000062E4E /* ASLayoutTestNode.h */, CCE4F9B71F0DBA5000062E4E /* ASLayoutTestNode.mm */, - 052EE0651A159FEF002C6279 /* ASMultiplexImageNodeTests.m */, - 058D0A32195D057000B7D73C /* ASMutableAttributedStringBuilderTests.m */, - BB5FC3CD1F9BA688007F191E /* ASNavigationControllerTests.m */, - CC11F9791DB181180024D77B /* ASNetworkImageNodeTests.m */, + 052EE0651A159FEF002C6279 /* ASMultiplexImageNodeTests.mm */, + 058D0A32195D057000B7D73C /* ASMutableAttributedStringBuilderTests.mm */, + BB5FC3CD1F9BA688007F191E /* ASNavigationControllerTests.mm */, + CC11F9791DB181180024D77B /* ASNetworkImageNodeTests.mm */, ACF6ED591B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm */, - AE6987C01DD04E1000B9E458 /* ASPagerNodeTests.m */, + AE6987C01DD04E1000B9E458 /* ASPagerNodeTests.mm */, CC8B05D41D73836400F54286 /* ASPerformanceTestContext.h */, - CC8B05D51D73836400F54286 /* ASPerformanceTestContext.m */, - CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */, + CC8B05D51D73836400F54286 /* ASPerformanceTestContext.mm */, + CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.mm */, ACF6ED5A1B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm */, - CCAA0B81206ADECB0057B336 /* ASRecursiveUnfairLockTests.m */, + CCAA0B81206ADECB0057B336 /* ASRecursiveUnfairLockTests.mm */, 7AB338681C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm */, - 4E9127681F64157600499623 /* ASRunLoopQueueTests.m */, - E586F96B1F9F9E2900ECE00E /* ASScrollNodeTests.m */, + 4E9127681F64157600499623 /* ASRunLoopQueueTests.mm */, + E586F96B1F9F9E2900ECE00E /* ASScrollNodeTests.mm */, 056D21501ABCEDA1001107EF /* ASSnapshotTestCase.h */, - 05EA6FE61AC0966E00E35788 /* ASSnapshotTestCase.m */, + 05EA6FE61AC0966E00E35788 /* ASSnapshotTestCase.mm */, ACF6ED5B1B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm */, - BB5FC3D01F9C9389007F191E /* ASTabBarControllerTests.m */, + BB5FC3D01F9C9389007F191E /* ASTabBarControllerTests.mm */, 3C9C128419E616EF00E942A0 /* ASTableViewTests.mm */, - CC4981B21D1A02BE004E13CC /* ASTableViewThrashTests.m */, - 058D0A33195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.m */, + CC4981B21D1A02BE004E13CC /* ASTableViewThrashTests.mm */, + 058D0A33195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.mm */, AE440174210FB7CF00B36DA2 /* ASTextKitFontSizeAdjusterTests.mm */, 254C6B531BF8FF2A003EC431 /* ASTextKitTests.mm */, 254C6B511BF8FE6D003EC431 /* ASTextKitTruncationTests.mm */, - C057D9BC20B5453D00FC9112 /* ASTextNode2SnapshotTests.m */, - CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.m */, - 81E95C131D62639600336598 /* ASTextNodeSnapshotTests.m */, - 058D0A36195D057000B7D73C /* ASTextNodeTests.m */, + C057D9BC20B5453D00FC9112 /* ASTextNode2SnapshotTests.mm */, + CC8B05D71D73979700F54286 /* ASTextNodePerformanceTests.mm */, + 81E95C131D62639600336598 /* ASTextNodeSnapshotTests.mm */, + 058D0A36195D057000B7D73C /* ASTextNodeTests.mm */, 058D0A37195D057000B7D73C /* ASTextNodeWordKernerTests.mm */, CCE4F9BC1F0ECE5200062E4E /* ASTLayoutFixture.h */, CCE4F9BD1F0ECE5200062E4E /* ASTLayoutFixture.mm */, - 4496D0721FA9EA6B001CC8D5 /* ASTraitCollectionTests.m */, - CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.m */, - AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.m */, - CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.m */, - 83A7D95D1D446A6E00BF333E /* ASWeakMapTests.m */, - CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.m */, + CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.mm */, + AEEC47E31C21D3D200EC1693 /* ASVideoNodeTests.mm */, + CCA221D21D6FA7EF00AF6A0F /* ASViewControllerTests.mm */, + 83A7D95D1D446A6E00BF333E /* ASWeakMapTests.mm */, + CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.mm */, 695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */, 057D02C01AC0A66700C7AC3C /* AsyncDisplayKitTestHost */, CC583ABF1EF9BAB400134156 /* Common */, @@ -1353,9 +1389,9 @@ 25B171EA1C12242700508A7A /* Data Controller */, 058D09F7195D050800B7D73C /* Transactions */, 3917EBD21E9C2FC400D04A01 /* _ASCollectionReusableView.h */, - 3917EBD31E9C2FC400D04A01 /* _ASCollectionReusableView.m */, + 3917EBD31E9C2FC400D04A01 /* _ASCollectionReusableView.mm */, CC0F885E1E4280B800576FED /* _ASCollectionViewCell.h */, - CC0F885D1E4280B800576FED /* _ASCollectionViewCell.m */, + CC0F885D1E4280B800576FED /* _ASCollectionViewCell.mm */, 058D09E2195D050800B7D73C /* _ASDisplayLayer.h */, 058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */, 058D09E4195D050800B7D73C /* _ASDisplayView.h */, @@ -1367,22 +1403,22 @@ 054963471A1EA066000F8E56 /* ASBasicImageDownloader.h */, 054963481A1EA066000F8E56 /* ASBasicImageDownloader.mm */, 299DA1A71A828D2900162D41 /* ASBatchContext.h */, - 299DA1A81A828D2900162D41 /* ASBatchContext.m */, + 299DA1A81A828D2900162D41 /* ASBatchContext.mm */, E5C347B01ECB3D9200EC4BE4 /* ASBatchFetchingDelegate.h */, 205F0E1B1B373A2C007741D0 /* ASCollectionViewLayoutController.h */, - 205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.m */, + 205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.mm */, 68C215561DE10D330019C4BC /* ASCollectionViewLayoutInspector.h */, - 68C215571DE10D330019C4BC /* ASCollectionViewLayoutInspector.m */, + 68C215571DE10D330019C4BC /* ASCollectionViewLayoutInspector.mm */, 696F01EA1DD2AF450049FBD5 /* ASEventLog.h */, 696F01EB1DD2AF450049FBD5 /* ASEventLog.mm */, CCDC9B4B200991D10063C1F8 /* ASGraphicsContext.h */, - CCDC9B4C200991D10063C1F8 /* ASGraphicsContext.m */, + CCDC9B4C200991D10063C1F8 /* ASGraphicsContext.mm */, E5B225271F1790B5001E1431 /* ASHashing.h */, - E5B225261F1790B5001E1431 /* ASHashing.m */, + E5B225261F1790B5001E1431 /* ASHashing.mm */, 058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */, 058D09E7195D050800B7D73C /* ASHighlightOverlayLayer.mm */, 68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */, - 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */, + 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.mm */, 05F20AA31A15733C00DCA68A /* ASImageProtocols.h */, CC5601391F06E9A700DC4FBE /* ASIntegerMap.h */, CC56013A1F06E9A700DC4FBE /* ASIntegerMap.mm */, @@ -1391,43 +1427,42 @@ 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */, 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */, 058D09E8195D050800B7D73C /* ASMutableAttributedStringBuilder.h */, - 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.m */, + 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.mm */, 6907C2561DC4ECFE00374C66 /* ASObjectDescriptionHelpers.h */, - 6907C2571DC4ECFE00374C66 /* ASObjectDescriptionHelpers.m */, + 6907C2571DC4ECFE00374C66 /* ASObjectDescriptionHelpers.mm */, CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */, - CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */, + CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.mm */, 68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */, - 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */, + 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.mm */, 055F1A3619ABD413004DAFF1 /* ASRangeController.h */, 055F1A3719ABD413004DAFF1 /* ASRangeController.mm */, 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */, CCAA0B7D206ADBF30057B336 /* ASRecursiveUnfairLock.h */, - CCAA0B7E206ADBF30057B336 /* ASRecursiveUnfairLock.m */, + CCAA0B7E206ADBF30057B336 /* ASRecursiveUnfairLock.mm */, 81EE384D1C8E94F000456208 /* ASRunLoopQueue.h */, 81EE384E1C8E94F000456208 /* ASRunLoopQueue.mm */, 296A0A311A951715005ACEAA /* ASScrollDirection.h */, - 205F0E111B371BD7007741D0 /* ASScrollDirection.m */, + 205F0E111B371BD7007741D0 /* ASScrollDirection.mm */, 4640521B1A3F83C40061C0BA /* ASTableLayoutController.h */, - 4640521C1A3F83C40061C0BA /* ASTableLayoutController.m */, + 4640521C1A3F83C40061C0BA /* ASTableLayoutController.mm */, 058D0A12195D050800B7D73C /* ASThread.h */, CC4C2A751D88E3BF0039ACAB /* ASTraceEvent.h */, - CC4C2A761D88E3BF0039ACAB /* ASTraceEvent.m */, + CC4C2A761D88E3BF0039ACAB /* ASTraceEvent.mm */, 9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */, - 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */, + 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.mm */, 68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */, - 68B8A4E01CBDB958007E4543 /* ASWeakProxy.m */, + 68B8A4E01CBDB958007E4543 /* ASWeakProxy.mm */, CC3B20871C3F7A5400798563 /* ASWeakSet.h */, - CC3B20881C3F7A5400798563 /* ASWeakSet.m */, + CC3B20881C3F7A5400798563 /* ASWeakSet.mm */, 205F0E1F1B376416007741D0 /* CoreGraphics+ASConvenience.h */, - 205F0E201B376416007741D0 /* CoreGraphics+ASConvenience.m */, DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */, DBC452DA1C5BF64600B16017 /* NSArray+Diffing.mm */, CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */, - CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.m */, + CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.mm */, 058D09F5195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.h */, - 058D09F6195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m */, + 058D09F6195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.mm */, 205F0E0D1B371875007741D0 /* UICollectionViewLayout+ASConvenience.h */, - 205F0E0E1B371875007741D0 /* UICollectionViewLayout+ASConvenience.m */, + 205F0E0E1B371875007741D0 /* UICollectionViewLayout+ASConvenience.mm */, 058D09FF195D050800B7D73C /* UIView+ASConvenience.h */, ); path = Details; @@ -1439,10 +1474,10 @@ 058D09F8195D050800B7D73C /* _ASAsyncTransaction.h */, 058D09F9195D050800B7D73C /* _ASAsyncTransaction.mm */, 058D09FB195D050800B7D73C /* _ASAsyncTransactionContainer.h */, - 058D09FC195D050800B7D73C /* _ASAsyncTransactionContainer.m */, + 058D09FC195D050800B7D73C /* _ASAsyncTransactionContainer.mm */, 058D09FA195D050800B7D73C /* _ASAsyncTransactionContainer+Private.h */, 058D09FD195D050800B7D73C /* _ASAsyncTransactionGroup.h */, - 058D09FE195D050800B7D73C /* _ASAsyncTransactionGroup.m */, + 058D09FE195D050800B7D73C /* _ASAsyncTransactionGroup.mm */, ); path = Transactions; sourceTree = ""; @@ -1457,71 +1492,72 @@ 058D0A03195D050800B7D73C /* _ASCoreAnimationExtras.h */, 058D0A04195D050800B7D73C /* _ASCoreAnimationExtras.mm */, AC026B6D1BD57DBF00BBC17E /* _ASHierarchyChangeSet.h */, + C018DF20216BF26600181FDA /* ASAbstractLayoutController+FrameworkPrivate.h */, AC026B6E1BD57DBF00BBC17E /* _ASHierarchyChangeSet.mm */, 058D0A05195D050800B7D73C /* _ASPendingState.h */, 058D0A06195D050800B7D73C /* _ASPendingState.mm */, 058D0A07195D050800B7D73C /* _ASScopeTimer.h */, DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */, - DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.m */, + DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.mm */, 2967F9E11AB0A4CF0072E4AB /* ASBasicImageDownloaderInternal.h */, 044285051BAA63FE00D16268 /* ASBatchFetching.h */, - 044285061BAA63FE00D16268 /* ASBatchFetching.m */, + 044285061BAA63FE00D16268 /* ASBatchFetching.mm */, CC87BB941DA8193C0090E380 /* ASCellNode+Internal.h */, CC2E317F1DAC353700EEE891 /* ASCollectionView+Undeprecated.h */, CC0F885A1E42807F00576FED /* ASCollectionViewFlowLayoutInspector.h */, - CC0F88591E42807F00576FED /* ASCollectionViewFlowLayoutInspector.m */, + CC0F88591E42807F00576FED /* ASCollectionViewFlowLayoutInspector.mm */, FA4FAF14200A850200E735BD /* ASControlNode+Private.h */, 9F98C0231DBDF2A300476D92 /* ASControlTargetAction.h */, - 9F98C0241DBDF2A300476D92 /* ASControlTargetAction.m */, + 9F98C0241DBDF2A300476D92 /* ASControlTargetAction.mm */, 8B0768B11CE752EC002E1453 /* ASDefaultPlaybackButton.h */, - 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.m */, + 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.mm */, AEB7B0181C5962EA00662EF4 /* ASDefaultPlayButton.h */, - AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */, + AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.mm */, CC54A81B1D70077A00296A24 /* ASDispatch.h */, - E5B2252D1F17E521001E1431 /* ASDispatch.m */, + E5B2252D1F17E521001E1431 /* ASDispatch.mm */, 058D0A08195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm */, 058D0A09195D050800B7D73C /* ASDisplayNode+DebugTiming.h */, 058D0A0A195D050800B7D73C /* ASDisplayNode+DebugTiming.mm */, DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */, 058D0A0B195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm */, 690BC8BF20F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.h */, - 690BC8C020F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.m */, + 690BC8C020F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.mm */, 058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */, 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */, CCA282C61E9EB64B0037E8B7 /* ASDisplayNodeTipState.h */, - CCA282C71E9EB64B0037E8B7 /* ASDisplayNodeTipState.m */, + CCA282C71E9EB64B0037E8B7 /* ASDisplayNodeTipState.mm */, 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */, 058D0A0D195D050800B7D73C /* ASImageNode+CGExtras.h */, - 058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.m */, + 058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.mm */, 6900C5F31E8072DA00BCD75C /* ASImageNode+Private.h */, ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */, - ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.m */, + ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.mm */, CCA282C21E9EAE630037E8B7 /* ASLayerBackingTipProvider.h */, - CCA282C31E9EAE630037E8B7 /* ASLayerBackingTipProvider.m */, + CCA282C31E9EAE630037E8B7 /* ASLayerBackingTipProvider.mm */, E52405B41C8FEF16004DC8E7 /* ASLayoutTransition.h */, E52405B21C8FEF03004DC8E7 /* ASLayoutTransition.mm */, CC2F65EC1E5FFB1600DA57C9 /* ASMutableElementMap.h */, - CC2F65ED1E5FFB1600DA57C9 /* ASMutableElementMap.m */, + CC2F65ED1E5FFB1600DA57C9 /* ASMutableElementMap.mm */, CCED5E402020D41600395C40 /* ASNetworkImageLoadInfo+Private.h */, CC3B20811C3F76D600798563 /* ASPendingStateController.h */, CC3B20821C3F76D600798563 /* ASPendingStateController.mm */, CC55A70F1E52A0F200594372 /* ASResponderChainEnumerator.h */, - CC55A7101E52A0F200594372 /* ASResponderChainEnumerator.m */, + CC55A7101E52A0F200594372 /* ASResponderChainEnumerator.mm */, CC512B841DAC45C60054848E /* ASTableView+Undeprecated.h */, CCA282BE1E9EAE010037E8B7 /* ASTip.h */, - CCA282BF1E9EAE010037E8B7 /* ASTip.m */, + CCA282BF1E9EAE010037E8B7 /* ASTip.mm */, CCA282CA1E9EB73E0037E8B7 /* ASTipNode.h */, - CCA282CB1E9EB73E0037E8B7 /* ASTipNode.m */, + CCA282CB1E9EB73E0037E8B7 /* ASTipNode.mm */, CCA282BA1E9EABDD0037E8B7 /* ASTipProvider.h */, - CCA282BB1E9EABDD0037E8B7 /* ASTipProvider.m */, + CCA282BB1E9EABDD0037E8B7 /* ASTipProvider.mm */, CCA282B21E9EA7310037E8B7 /* ASTipsController.h */, - CCA282B31E9EA7310037E8B7 /* ASTipsController.m */, + CCA282B31E9EA7310037E8B7 /* ASTipsController.mm */, CCA282CE1E9EBF6C0037E8B7 /* ASTipsWindow.h */, - CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.m */, + CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.mm */, 0442850B1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.h */, - 0442850C1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.m */, + 0442850C1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.mm */, 83A7D9581D44542100BF333E /* ASWeakMap.h */, - 83A7D9591D44542100BF333E /* ASWeakMap.m */, + 83A7D9591D44542100BF333E /* ASWeakMap.mm */, ); path = Private; sourceTree = ""; @@ -1530,12 +1566,12 @@ isa = PBXGroup; children = ( 058D0A43195D058D00B7D73C /* ASAssert.h */, - CCA5F62D1EECC2A80060C137 /* ASAssert.m */, + CCA5F62D1EECC2A80060C137 /* ASAssert.mm */, 0516FA3A1A15563400B4EBED /* ASAvailability.h */, 058D0A44195D058D00B7D73C /* ASBaseDefines.h */, 1950C4481A3BB5C1005C8279 /* ASEqualityHelpers.h */, 0516FA3B1A15563400B4EBED /* ASLog.h */, - CCB1F9591EFB60A5009C7475 /* ASLog.m */, + CCB1F9591EFB60A5009C7475 /* ASLog.mm */, CCB1F95B1EFB6316009C7475 /* ASSignpost.h */, ); path = Base; @@ -1545,7 +1581,7 @@ isa = PBXGroup; children = ( B30BF6501C5964B0004FCD53 /* ASLayoutManager.h */, - B30BF6511C5964B0004FCD53 /* ASLayoutManager.m */, + B30BF6511C5964B0004FCD53 /* ASLayoutManager.mm */, 257754951BEE44CD00737CA5 /* ASTextKitAttributes.h */, 257754941BEE44CD00737CA5 /* ASTextKitAttributes.mm */, 257754BA1BEE458E00737CA5 /* ASTextKitComponents.h */, @@ -1553,9 +1589,9 @@ 257754961BEE44CD00737CA5 /* ASTextKitContext.h */, 257754971BEE44CD00737CA5 /* ASTextKitContext.mm */, 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */, - 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m */, + 257754B81BEE458E00737CA5 /* ASTextKitCoreTextAdditions.mm */, 257754981BEE44CD00737CA5 /* ASTextKitEntityAttribute.h */, - 257754991BEE44CD00737CA5 /* ASTextKitEntityAttribute.m */, + 257754991BEE44CD00737CA5 /* ASTextKitEntityAttribute.mm */, A32FEDD31C501B6A004F642A /* ASTextKitFontSizeAdjuster.h */, 9C8898BA1C738B9800D6B02E /* ASTextKitFontSizeAdjuster.mm */, 257754931BEE44CD00737CA5 /* ASTextKitRenderer.h */, @@ -1571,7 +1607,7 @@ 257754A31BEE44CD00737CA5 /* ASTextKitTruncating.h */, 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */, 257754B91BEE458E00737CA5 /* ASTextNodeWordKerner.h */, - 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */, + 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.mm */, ); name = TextKit; sourceTree = ""; @@ -1584,11 +1620,11 @@ 464052191A3F83C40061C0BA /* ASDataController.h */, 4640521A1A3F83C40061C0BA /* ASDataController.mm */, DE8BEABF1C2DF3FC00D57C12 /* ASDelegateProxy.h */, - DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.m */, + DE8BEAC01C2DF3FC00D57C12 /* ASDelegateProxy.mm */, E5B077FD1E69F4EB00C24B5B /* ASElementMap.h */, - E5B077FE1E69F4EB00C24B5B /* ASElementMap.m */, + E5B077FE1E69F4EB00C24B5B /* ASElementMap.mm */, AC6145401D8AFAE8003D62A2 /* ASSection.h */, - AC6145421D8AFD4F003D62A2 /* ASSection.m */, + AC6145421D8AFD4F003D62A2 /* ASSection.mm */, ); name = "Data Controller"; sourceTree = ""; @@ -1596,8 +1632,8 @@ 690ED5911E36D118000627C0 /* tvOS */ = { isa = PBXGroup; children = ( - 690ED5931E36D118000627C0 /* ASControlNode+tvOS.m */, - 690ED5951E36D118000627C0 /* ASImageNode+tvOS.m */, + 690ED5931E36D118000627C0 /* ASControlNode+tvOS.mm */, + 690ED5951E36D118000627C0 /* ASImageNode+tvOS.mm */, ); path = tvOS; sourceTree = ""; @@ -1624,7 +1660,7 @@ ACF6ED181B17843500DA7C62 /* ASAbsoluteLayoutSpec.h */, ACF6ED191B17843500DA7C62 /* ASAbsoluteLayoutSpec.mm */, 9C5586671BD549CB00B50E3A /* ASAsciiArtBoxCreator.h */, - 9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.m */, + 9C5586681BD549CB00B50E3A /* ASAsciiArtBoxCreator.mm */, ACF6ED011B17843500DA7C62 /* ASBackgroundLayoutSpec.h */, ACF6ED021B17843500DA7C62 /* ASBackgroundLayoutSpec.mm */, ACF6ED031B17843500DA7C62 /* ASCenterLayoutSpec.h */, @@ -1676,15 +1712,15 @@ CC583ABF1EF9BAB400134156 /* Common */ = { isa = PBXGroup; children = ( - CC583AC01EF9BAB400134156 /* ASDisplayNode+OCMock.m */, + CC583AC01EF9BAB400134156 /* ASDisplayNode+OCMock.mm */, CC583AC11EF9BAB400134156 /* ASTestCase.h */, - CC583AC21EF9BAB400134156 /* ASTestCase.m */, + CC583AC21EF9BAB400134156 /* ASTestCase.mm */, CC583AC31EF9BAB400134156 /* ASXCTExtensions.h */, CCE4F9BB1F0EA67F00062E4E /* debugbreak.h */, CC583AC41EF9BAB400134156 /* NSInvocation+ASTestHelpers.h */, - CC583AC51EF9BAB400134156 /* NSInvocation+ASTestHelpers.m */, + CC583AC51EF9BAB400134156 /* NSInvocation+ASTestHelpers.mm */, CC583AC61EF9BAB400134156 /* OCMockObject+ASAdditions.h */, - CC583AC71EF9BAB400134156 /* OCMockObject+ASAdditions.m */, + CC583AC71EF9BAB400134156 /* OCMockObject+ASAdditions.mm */, ); path = Common; sourceTree = ""; @@ -1703,13 +1739,13 @@ isa = PBXGroup; children = ( CCCCCCC31EC3EF060087FE10 /* ASTextDebugOption.h */, - CCCCCCC41EC3EF060087FE10 /* ASTextDebugOption.m */, + CCCCCCC41EC3EF060087FE10 /* ASTextDebugOption.mm */, CCCCCCC51EC3EF060087FE10 /* ASTextInput.h */, - CCCCCCC61EC3EF060087FE10 /* ASTextInput.m */, + CCCCCCC61EC3EF060087FE10 /* ASTextInput.mm */, CCCCCCC71EC3EF060087FE10 /* ASTextLayout.h */, - CCCCCCC81EC3EF060087FE10 /* ASTextLayout.m */, + CCCCCCC81EC3EF060087FE10 /* ASTextLayout.mm */, CCCCCCC91EC3EF060087FE10 /* ASTextLine.h */, - CCCCCCCA1EC3EF060087FE10 /* ASTextLine.m */, + CCCCCCCA1EC3EF060087FE10 /* ASTextLine.mm */, ); path = Component; sourceTree = ""; @@ -1718,9 +1754,9 @@ isa = PBXGroup; children = ( CCCCCCCC1EC3EF060087FE10 /* ASTextAttribute.h */, - CCCCCCCD1EC3EF060087FE10 /* ASTextAttribute.m */, + CCCCCCCD1EC3EF060087FE10 /* ASTextAttribute.mm */, CCCCCCCE1EC3EF060087FE10 /* ASTextRunDelegate.h */, - CCCCCCCF1EC3EF060087FE10 /* ASTextRunDelegate.m */, + CCCCCCCF1EC3EF060087FE10 /* ASTextRunDelegate.mm */, ); path = String; sourceTree = ""; @@ -1729,11 +1765,11 @@ isa = PBXGroup; children = ( CCCCCCD11EC3EF060087FE10 /* ASTextUtilities.h */, - CCCCCCD21EC3EF060087FE10 /* ASTextUtilities.m */, + CCCCCCD21EC3EF060087FE10 /* ASTextUtilities.mm */, CCCCCCE51EC3F0FC0087FE10 /* NSAttributedString+ASText.h */, - CCCCCCE61EC3F0FC0087FE10 /* NSAttributedString+ASText.m */, + CCCCCCE61EC3F0FC0087FE10 /* NSAttributedString+ASText.mm */, CCCCCCD31EC3EF060087FE10 /* NSParagraphStyle+ASText.h */, - CCCCCCD41EC3EF060087FE10 /* NSParagraphStyle+ASText.m */, + CCCCCCD41EC3EF060087FE10 /* NSParagraphStyle+ASText.mm */, ); path = Utility; sourceTree = ""; @@ -1752,7 +1788,7 @@ isa = PBXGroup; children = ( CCBD05DF1E4147B000D18509 /* ASIGListAdapterBasedDataSource.h */, - CCBD05DE1E4147B000D18509 /* ASIGListAdapterBasedDataSource.m */, + CCBD05DE1E4147B000D18509 /* ASIGListAdapterBasedDataSource.mm */, ); name = "Collection Data Adapter"; sourceTree = ""; @@ -1761,9 +1797,9 @@ isa = PBXGroup; children = ( CC034A111E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.h */, - CC034A121E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.m */, + CC034A121E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.mm */, CCE04B201E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.h */, - CCE04B211E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.m */, + CCE04B211E313EB9006AEBBB /* IGListAdapter+AsyncDisplayKit.mm */, ); name = "IGListKit Support"; sourceTree = ""; @@ -1772,9 +1808,9 @@ isa = PBXGroup; children = ( 764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */, - 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */, + 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.mm */, CCA282B61E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.h */, - CCA282B71E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.m */, + CCA282B71E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.mm */, ); path = Debug; sourceTree = ""; @@ -1783,7 +1819,7 @@ isa = PBXGroup; children = ( E5667E8B1F33871300FA6FC0 /* _ASCollectionGalleryLayoutInfo.h */, - E5667E8D1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.m */, + E5667E8D1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.mm */, E5775AFB1F13CE9F00CAC9BC /* _ASCollectionGalleryLayoutItem.h */, E5775AFD1F13CF7400CAC9BC /* _ASCollectionGalleryLayoutItem.mm */, E58E9E471E941DA5004CFC59 /* ASCollectionLayout.h */, @@ -1792,7 +1828,7 @@ E5775B031F16759F00CAC9BC /* ASCollectionLayoutCache.mm */, E5B5B9D01E9BAD9800A6B726 /* ASCollectionLayoutContext+Private.h */, E5855DEE1EBB4D83003639AE /* ASCollectionLayoutDefines.h */, - E5855DED1EBB4D83003639AE /* ASCollectionLayoutDefines.m */, + E5855DED1EBB4D83003639AE /* ASCollectionLayoutDefines.mm */, E5775AFF1F13D25400CAC9BC /* ASCollectionLayoutState+Private.h */, ); name = "Collection Layout"; @@ -1802,16 +1838,16 @@ isa = PBXGroup; children = ( E58E9E3D1E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.h */, - E58E9E3E1E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.m */, + E58E9E3E1E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.mm */, E5E2D72D1EA780C4005C24C6 /* ASCollectionGalleryLayoutDelegate.h */, E5E2D72F1EA780DF005C24C6 /* ASCollectionGalleryLayoutDelegate.mm */, E58E9E3F1E941D74004CFC59 /* ASCollectionLayoutContext.h */, - E58E9E401E941D74004CFC59 /* ASCollectionLayoutContext.m */, + E58E9E401E941D74004CFC59 /* ASCollectionLayoutContext.mm */, E58E9E411E941D74004CFC59 /* ASCollectionLayoutDelegate.h */, E5E281731E71C833006B67C2 /* ASCollectionLayoutState.h */, E5E281751E71C845006B67C2 /* ASCollectionLayoutState.mm */, E54E81FA1EB357BD00FFE8E1 /* ASPageTable.h */, - E54E81FB1EB357BD00FFE8E1 /* ASPageTable.m */, + E54E81FB1EB357BD00FFE8E1 /* ASPageTable.mm */, ); name = "Collection Layout"; sourceTree = ""; @@ -1878,6 +1914,7 @@ CC0F88621E4281E200576FED /* ASSectionController.h in Headers */, CCB1F95C1EFB6350009C7475 /* ASSignpost.h in Headers */, A2763D7A1CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h in Headers */, + C018DF21216BF26700181FDA /* ASAbstractLayoutController+FrameworkPrivate.h in Headers */, 34EFC7611B701C9C00AD841F /* ASBackgroundLayoutSpec.h in Headers */, B35062591B010F070018CF92 /* ASBaseDefines.h in Headers */, B35062131B010EFD0018CF92 /* ASBasicImageDownloader.h in Headers */, @@ -2090,8 +2127,6 @@ 058D09B8195D04C000B7D73C /* Sources */, 058D09B9195D04C000B7D73C /* Frameworks */, 058D09BA195D04C000B7D73C /* Resources */, - 3B9D88CDF51B429C8409E4B6 /* [CP] Copy Pods Resources */, - B130AB1AC0A1E5162E211C19 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -2214,36 +2249,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 3B9D88CDF51B429C8409E4B6 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - B130AB1AC0A1E5162E211C19 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -2251,8 +2256,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 057D02C71AC0A66700C7AC3C /* AppDelegate.m in Sources */, - 057D02C41AC0A66700C7AC3C /* main.m in Sources */, + 057D02C71AC0A66700C7AC3C /* AppDelegate.mm in Sources */, + 057D02C41AC0A66700C7AC3C /* main.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2260,81 +2265,82 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CCEDDDD9200C518800FFCD0A /* ASConfigurationTests.m in Sources */, + CCEDDDD9200C518800FFCD0A /* ASConfigurationTests.mm in Sources */, AE440175210FB7CF00B36DA2 /* ASTextKitFontSizeAdjusterTests.mm in Sources */, - E51B78BF1F028ABF00E32604 /* ASLayoutFlatteningTests.m in Sources */, - 4496D0731FA9EA6B001CC8D5 /* ASTraitCollectionTests.m in Sources */, - 29CDC2E21AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.m in Sources */, - CC583AD71EF9BDC100134156 /* NSInvocation+ASTestHelpers.m in Sources */, - CC051F1F1D7A286A006434CB /* ASCALayerTests.m in Sources */, - 242995D31B29743C00090100 /* ASBasicImageDownloaderTests.m in Sources */, - 296A0A351A951ABF005ACEAA /* ASBatchFetchingTests.m in Sources */, + E51B78BF1F028ABF00E32604 /* ASLayoutFlatteningTests.mm in Sources */, + 29CDC2E21AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.mm in Sources */, + CC583AD71EF9BDC100134156 /* NSInvocation+ASTestHelpers.mm in Sources */, + CC051F1F1D7A286A006434CB /* ASCALayerTests.mm in Sources */, + 242995D31B29743C00090100 /* ASBasicImageDownloaderTests.mm in Sources */, + 296A0A351A951ABF005ACEAA /* ASBatchFetchingTests.mm in Sources */, ACF6ED5C1B178DC700DA7C62 /* ASCenterLayoutSpecSnapshotTests.mm in Sources */, 9F06E5CD1B4CAF4200F015D8 /* ASCollectionViewTests.mm in Sources */, - 2911485C1A77147A005D0878 /* ASControlNodeTests.m in Sources */, - CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.m in Sources */, - F711994E1D20C21100568860 /* ASDisplayNodeExtrasTests.m in Sources */, - BB5FC3CE1F9BA689007F191E /* ASNavigationControllerTests.m in Sources */, + 2911485C1A77147A005D0878 /* ASControlNodeTests.mm in Sources */, + CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.mm in Sources */, + F711994E1D20C21100568860 /* ASDisplayNodeExtrasTests.mm in Sources */, + BB5FC3CE1F9BA689007F191E /* ASNavigationControllerTests.mm in Sources */, ACF6ED5D1B178DC700DA7C62 /* ASDimensionTests.mm in Sources */, - BB5FC3D11F9C9389007F191E /* ASTabBarControllerTests.m in Sources */, + BB5FC3D11F9C9389007F191E /* ASTabBarControllerTests.mm in Sources */, 695BE2551DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm in Sources */, - CCA221D31D6FA7EF00AF6A0F /* ASViewControllerTests.m in Sources */, - 058D0A38195D057000B7D73C /* ASDisplayLayerTests.m in Sources */, - 2538B6F31BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m in Sources */, - CC583AD61EF9BDBE00134156 /* ASTestCase.m in Sources */, - 058D0A39195D057000B7D73C /* ASDisplayNodeAppearanceTests.m in Sources */, - CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m in Sources */, - AE6987C11DD04E1000B9E458 /* ASPagerNodeTests.m in Sources */, + CCA221D31D6FA7EF00AF6A0F /* ASViewControllerTests.mm in Sources */, + 058D0A38195D057000B7D73C /* ASDisplayLayerTests.mm in Sources */, + 2538B6F31BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.mm in Sources */, + CC583AD61EF9BDBE00134156 /* ASTestCase.mm in Sources */, + 058D0A39195D057000B7D73C /* ASDisplayNodeAppearanceTests.mm in Sources */, + CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.mm in Sources */, + AE6987C11DD04E1000B9E458 /* ASPagerNodeTests.mm in Sources */, 058D0A3A195D057000B7D73C /* ASDisplayNodeTests.mm in Sources */, 696FCB311D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm in Sources */, - CC583AD81EF9BDC300134156 /* OCMockObject+ASAdditions.m in Sources */, - 69FEE53D1D95A9AF0086F066 /* ASLayoutElementStyleTests.m in Sources */, - 4E9127691F64157600499623 /* ASRunLoopQueueTests.m in Sources */, - CC4981B31D1A02BE004E13CC /* ASTableViewThrashTests.m in Sources */, - CC54A81E1D7008B300296A24 /* ASDispatchTests.m in Sources */, + CC583AD81EF9BDC300134156 /* OCMockObject+ASAdditions.mm in Sources */, + 69FEE53D1D95A9AF0086F066 /* ASLayoutElementStyleTests.mm in Sources */, + 4E9127691F64157600499623 /* ASRunLoopQueueTests.mm in Sources */, + CC4981B31D1A02BE004E13CC /* ASTableViewThrashTests.mm in Sources */, + CC54A81E1D7008B300296A24 /* ASDispatchTests.mm in Sources */, F3F698D2211CAD4600800CB1 /* ASDisplayViewAccessibilityTests.mm in Sources */, - CCE4F9B31F0D60AC00062E4E /* ASIntegerMapTests.m in Sources */, - 058D0A3B195D057000B7D73C /* ASDisplayNodeTestsHelper.m in Sources */, - 83A7D95E1D446A6E00BF333E /* ASWeakMapTests.m in Sources */, - 056D21551ABCEF50001107EF /* ASImageNodeSnapshotTests.m in Sources */, - AC026B581BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.m in Sources */, + CCE4F9B31F0D60AC00062E4E /* ASIntegerMapTests.mm in Sources */, + 058D0A3B195D057000B7D73C /* ASDisplayNodeTestsHelper.mm in Sources */, + 83A7D95E1D446A6E00BF333E /* ASWeakMapTests.mm in Sources */, + 056D21551ABCEF50001107EF /* ASImageNodeSnapshotTests.mm in Sources */, + AC026B581BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.mm in Sources */, ACF6ED5E1B178DC700DA7C62 /* ASInsetLayoutSpecSnapshotTests.mm in Sources */, - ACF6ED601B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.m in Sources */, - CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */, - 052EE0661A159FEF002C6279 /* ASMultiplexImageNodeTests.m in Sources */, - 058D0A3C195D057000B7D73C /* ASMutableAttributedStringBuilderTests.m in Sources */, - E586F96C1F9F9E2900ECE00E /* ASScrollNodeTests.m in Sources */, - CC8B05D81D73979700F54286 /* ASTextNodePerformanceTests.m in Sources */, - CC583AD91EF9BDC600134156 /* ASDisplayNode+OCMock.m in Sources */, - 697B315A1CFE4B410049936F /* ASEditableTextNodeTests.m in Sources */, + ACF6ED601B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.mm in Sources */, + CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.mm in Sources */, + 052EE0661A159FEF002C6279 /* ASMultiplexImageNodeTests.mm in Sources */, + 058D0A3C195D057000B7D73C /* ASMutableAttributedStringBuilderTests.mm in Sources */, + F325E48C21745F9E00AC93A4 /* ASButtonNodeTests.mm in Sources */, + E586F96C1F9F9E2900ECE00E /* ASScrollNodeTests.mm in Sources */, + CC8B05D81D73979700F54286 /* ASTextNodePerformanceTests.mm in Sources */, + CC583AD91EF9BDC600134156 /* ASDisplayNode+OCMock.mm in Sources */, + 697B315A1CFE4B410049936F /* ASEditableTextNodeTests.mm in Sources */, ACF6ED611B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm in Sources */, - CC8B05D61D73836400F54286 /* ASPerformanceTestContext.m in Sources */, - CC0AEEA41D66316E005D1C78 /* ASUICollectionViewTests.m in Sources */, + CC8B05D61D73836400F54286 /* ASPerformanceTestContext.mm in Sources */, + CC0AEEA41D66316E005D1C78 /* ASUICollectionViewTests.mm in Sources */, CCE4F9B51F0DA4F300062E4E /* ASLayoutEngineTests.mm in Sources */, 69B225671D72535E00B25B22 /* ASDisplayNodeLayoutTests.mm in Sources */, - C057D9BD20B5453D00FC9112 /* ASTextNode2SnapshotTests.m in Sources */, + C057D9BD20B5453D00FC9112 /* ASTextNode2SnapshotTests.mm in Sources */, ACF6ED621B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm in Sources */, 7AB338691C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm in Sources */, - CCDD148B1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.m in Sources */, + CCDD148B1EEDCD9D0020834E /* ASCollectionModernDataSourceTests.mm in Sources */, 1A6C00111FAB4EDD00D05926 /* ASCornerLayoutSpecSnapshotTests.mm in Sources */, 254C6B541BF8FF2A003EC431 /* ASTextKitTests.mm in Sources */, - 05EA6FE71AC0966E00E35788 /* ASSnapshotTestCase.m in Sources */, - CC35CEC620DD87280006448D /* ASCollectionsTests.m in Sources */, + 05EA6FE71AC0966E00E35788 /* ASSnapshotTestCase.mm in Sources */, + CC35CEC620DD87280006448D /* ASCollectionsTests.mm in Sources */, ACF6ED631B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm in Sources */, CCE4F9BA1F0DBB5000062E4E /* ASLayoutTestNode.mm in Sources */, - CCAA0B82206ADECB0057B336 /* ASRecursiveUnfairLockTests.m in Sources */, - 81E95C141D62639600336598 /* ASTextNodeSnapshotTests.m in Sources */, + CCAA0B82206ADECB0057B336 /* ASRecursiveUnfairLockTests.mm in Sources */, + 81E95C141D62639600336598 /* ASTextNodeSnapshotTests.mm in Sources */, 3C9C128519E616EF00E942A0 /* ASTableViewTests.mm in Sources */, - AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.m in Sources */, + AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.mm in Sources */, 254C6B521BF8FE6D003EC431 /* ASTextKitTruncationTests.mm in Sources */, - 058D0A3D195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.m in Sources */, + F325E490217460B100AC93A4 /* ASTextNode2Tests.mm in Sources */, + 058D0A3D195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.mm in Sources */, CC3B20901C3F892D00798563 /* ASBridgedPropertiesTests.mm in Sources */, CCE4F9BE1F0ECE5200062E4E /* ASTLayoutFixture.mm in Sources */, - 058D0A40195D057000B7D73C /* ASTextNodeTests.m in Sources */, - DBC453221C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.m in Sources */, + 058D0A40195D057000B7D73C /* ASTextNodeTests.mm in Sources */, + DBC453221C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.mm in Sources */, 058D0A41195D057000B7D73C /* ASTextNodeWordKernerTests.mm in Sources */, - DBC452DE1C5C6A6A00B16017 /* ArrayDiffingTests.m in Sources */, - CC11F97A1DB181180024D77B /* ASNetworkImageNodeTests.m in Sources */, + DBC452DE1C5C6A6A00B16017 /* ArrayDiffingTests.mm in Sources */, + CC11F97A1DB181180024D77B /* ASNetworkImageNodeTests.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2342,80 +2348,79 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E5B225291F1790EE001E1431 /* ASHashing.m in Sources */, + E5B225291F1790EE001E1431 /* ASHashing.mm in Sources */, DEB8ED7C1DD003D300DBDE55 /* ASLayoutTransition.mm in Sources */, - CCA5F62E1EECC2A80060C137 /* ASAssert.m in Sources */, - 9F98C0261DBE29E000476D92 /* ASControlTargetAction.m in Sources */, + CCA5F62E1EECC2A80060C137 /* ASAssert.mm in Sources */, + 9F98C0261DBE29E000476D92 /* ASControlTargetAction.mm in Sources */, 9C70F2091CDABA36007D6C76 /* ASViewController.mm in Sources */, - 3917EBD51E9C2FC400D04A01 /* _ASCollectionReusableView.m in Sources */, - CCA282D11E9EBF6C0037E8B7 /* ASTipsWindow.m in Sources */, - CCCCCCE41EC3EF060087FE10 /* NSParagraphStyle+ASText.m in Sources */, - 8BBBAB8D1CEBAF1E00107FC6 /* ASDefaultPlaybackButton.m in Sources */, - B30BF6541C59D889004FCD53 /* ASLayoutManager.m in Sources */, + 3917EBD51E9C2FC400D04A01 /* _ASCollectionReusableView.mm in Sources */, + CCA282D11E9EBF6C0037E8B7 /* ASTipsWindow.mm in Sources */, + CCCCCCE41EC3EF060087FE10 /* NSParagraphStyle+ASText.mm in Sources */, + 8BBBAB8D1CEBAF1E00107FC6 /* ASDefaultPlaybackButton.mm in Sources */, + B30BF6541C59D889004FCD53 /* ASLayoutManager.mm in Sources */, 92DD2FE71BF4D0850074C9DD /* ASMapNode.mm in Sources */, - CCA282B91E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.m in Sources */, - 636EA1A51C7FF4EF00EE152F /* ASDefaultPlayButton.m in Sources */, + CCA282B91E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.mm in Sources */, + 636EA1A51C7FF4EF00EE152F /* ASDefaultPlayButton.mm in Sources */, B350623D1B010EFD0018CF92 /* _ASAsyncTransaction.mm in Sources */, 6947B0C51E36B5040007C478 /* ASStackPositionedLayout.mm in Sources */, - B35062401B010EFD0018CF92 /* _ASAsyncTransactionContainer.m in Sources */, + B35062401B010EFD0018CF92 /* _ASAsyncTransactionContainer.mm in Sources */, AC026B721BD57DBF00BBC17E /* _ASHierarchyChangeSet.mm in Sources */, - B35062421B010EFD0018CF92 /* _ASAsyncTransactionGroup.m in Sources */, - CCA282BD1E9EABDD0037E8B7 /* ASTipProvider.m in Sources */, + B35062421B010EFD0018CF92 /* _ASAsyncTransactionGroup.mm in Sources */, + CCA282BD1E9EABDD0037E8B7 /* ASTipProvider.mm in Sources */, 9019FBC01ED8061D00C45F72 /* ASYogaUtilities.mm in Sources */, B350624A1B010EFD0018CF92 /* _ASCoreAnimationExtras.mm in Sources */, 68EE0DC01C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */, B35062101B010EFD0018CF92 /* _ASDisplayLayer.mm in Sources */, - 9C55866B1BD54A1900B50E3A /* ASAsciiArtBoxCreator.m in Sources */, + 9C55866B1BD54A1900B50E3A /* ASAsciiArtBoxCreator.mm in Sources */, B35062121B010EFD0018CF92 /* _ASDisplayView.mm in Sources */, DEFAD8131CC48914000527C4 /* ASVideoNode.mm in Sources */, - CCA282C11E9EAE010037E8B7 /* ASTip.m in Sources */, + CCA282C11E9EAE010037E8B7 /* ASTip.mm in Sources */, B350624C1B010EFD0018CF92 /* _ASPendingState.mm in Sources */, 698371DC1E4379CD00437585 /* ASNodeController+Beta.mm in Sources */, - CC6AA2DB1E9F03B900978E87 /* ASDisplayNode+Ancestry.m in Sources */, + CC6AA2DB1E9F03B900978E87 /* ASDisplayNode+Ancestry.mm in Sources */, 509E68621B3AEDA5009B9150 /* ASAbstractLayoutController.mm in Sources */, 254C6B861BF94F8A003EC431 /* ASTextKitContext.mm in Sources */, - DBDB83971C6E879900D0098C /* ASPagerFlowLayout.m in Sources */, - E5B078001E69F4EB00C24B5B /* ASElementMap.m in Sources */, + DBDB83971C6E879900D0098C /* ASPagerFlowLayout.mm in Sources */, + E5B078001E69F4EB00C24B5B /* ASElementMap.mm in Sources */, 9C8898BC1C738BA800D6B02E /* ASTextKitFontSizeAdjuster.mm in Sources */, - 690ED59B1E36D118000627C0 /* ASImageNode+tvOS.m in Sources */, + 690ED59B1E36D118000627C0 /* ASImageNode+tvOS.mm in Sources */, 0FAFDF7620EC1C90003A51C0 /* ASLayout+IGListKit.mm in Sources */, - CCDC9B4E200991D10063C1F8 /* ASGraphicsContext.m in Sources */, - CCCCCCD81EC3EF060087FE10 /* ASTextInput.m in Sources */, + CCDC9B4E200991D10063C1F8 /* ASGraphicsContext.mm in Sources */, + CCCCCCD81EC3EF060087FE10 /* ASTextInput.mm in Sources */, 34EFC7621B701CA400AD841F /* ASBackgroundLayoutSpec.mm in Sources */, - DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */, + DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.mm in Sources */, B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */, - B35062161B010EFD0018CF92 /* ASBatchContext.m in Sources */, + B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */, AC47D9421B3B891B00AAEE9D /* ASCellNode.mm in Sources */, - E58E9E451E941D74004CFC59 /* ASCollectionLayoutContext.m in Sources */, + E58E9E451E941D74004CFC59 /* ASCollectionLayoutContext.mm in Sources */, 34EFC7641B701CC600AD841F /* ASCenterLayoutSpec.mm in Sources */, 18C2ED831B9B7DE800F627B3 /* ASCollectionNode.mm in Sources */, E55D86331CA8A14000A0C26F /* ASLayoutElement.mm in Sources */, - 68FC85EC1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */, - CC55A7121E52A0F200594372 /* ASResponderChainEnumerator.m in Sources */, - CCED5E3F2020D36800395C40 /* ASNetworkImageLoadInfo.m in Sources */, - 68B8A4E41CBDB958007E4543 /* ASWeakProxy.m in Sources */, + 68FC85EC1CE29C7D00EDD713 /* ASVisibilityProtocols.mm in Sources */, + CC55A7121E52A0F200594372 /* ASResponderChainEnumerator.mm in Sources */, + CCED5E3F2020D36800395C40 /* ASNetworkImageLoadInfo.mm in Sources */, + 68B8A4E41CBDB958007E4543 /* ASWeakProxy.mm in Sources */, E5775B041F16759F00CAC9BC /* ASCollectionLayoutCache.mm in Sources */, 9C70F20A1CDBE949007D6C76 /* ASTableNode.mm in Sources */, 69CB62AE1CB8165900024920 /* _ASDisplayViewAccessiblity.mm in Sources */, B35061F61B010EFD0018CF92 /* ASCollectionView.mm in Sources */, - CCA282C51E9EAE630037E8B7 /* ASLayerBackingTipProvider.m in Sources */, - 509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.m in Sources */, + CCA282C51E9EAE630037E8B7 /* ASLayerBackingTipProvider.mm in Sources */, + 509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.mm in Sources */, B35061F91B010EFD0018CF92 /* ASControlNode.mm in Sources */, - 8021EC1F1D2B00B100799119 /* UIImage+ASConvenience.m in Sources */, - CCAA0B80206ADBF30057B336 /* ASRecursiveUnfairLock.m in Sources */, + 8021EC1F1D2B00B100799119 /* UIImage+ASConvenience.mm in Sources */, + CCAA0B80206ADBF30057B336 /* ASRecursiveUnfairLock.mm in Sources */, CCBDDD0620C62A2D00CBA922 /* ASMainThreadDeallocation.mm in Sources */, B35062181B010EFD0018CF92 /* ASDataController.mm in Sources */, - CCB1F95A1EFB60A5009C7475 /* ASLog.m in Sources */, - 767E7F8E1C90191D0066C000 /* AsyncDisplayKit+Debug.m in Sources */, - CCEDDDCB200C2AC300FFCD0A /* ASConfigurationInternal.m in Sources */, - CCCCCCD61EC3EF060087FE10 /* ASTextDebugOption.m in Sources */, + CCB1F95A1EFB60A5009C7475 /* ASLog.mm in Sources */, + 767E7F8E1C90191D0066C000 /* AsyncDisplayKit+Debug.mm in Sources */, + CCEDDDCB200C2AC300FFCD0A /* ASConfigurationInternal.mm in Sources */, + CCCCCCD61EC3EF060087FE10 /* ASTextDebugOption.mm in Sources */, 34EFC75C1B701BD200AD841F /* ASDimension.mm in Sources */, B350624E1B010EFD0018CF92 /* ASDisplayNode+AsyncDisplay.mm in Sources */, - E5667E8E1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.m in Sources */, - 25E327591C16819500A2170C /* ASPagerNode.m in Sources */, + E5667E8E1F33872700FA6FC0 /* _ASCollectionGalleryLayoutInfo.mm in Sources */, + 25E327591C16819500A2170C /* ASPagerNode.mm in Sources */, 636EA1A41C7FF4EC00EE152F /* NSArray+Diffing.mm in Sources */, B35062501B010EFD0018CF92 /* ASDisplayNode+DebugTiming.mm in Sources */, - DEC146B91C37A16A004A0EE7 /* ASCollectionInternal.m in Sources */, 254C6B891BF94F8A003EC431 /* ASTextKitRenderer+Positioning.mm in Sources */, 68355B341CB579B9001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */, E5711A301C840C96009619D4 /* ASCollectionElement.mm in Sources */, @@ -2425,94 +2430,93 @@ B35061FF1B010EFD0018CF92 /* ASDisplayNodeExtras.mm in Sources */, B35062011B010EFD0018CF92 /* ASEditableTextNode.mm in Sources */, 254C6B881BF94F8A003EC431 /* ASTextKitRenderer.mm in Sources */, - CC3B208C1C3F7A5400798563 /* ASWeakSet.m in Sources */, - B350621C1B010EFD0018CF92 /* ASTableLayoutController.m in Sources */, + CC3B208C1C3F7A5400798563 /* ASWeakSet.mm in Sources */, + B350621C1B010EFD0018CF92 /* ASTableLayoutController.mm in Sources */, B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */, - 9CC606651D24DF9E006581A0 /* NSIndexSet+ASHelpers.m in Sources */, - CC0F885F1E4280B800576FED /* _ASCollectionViewCell.m in Sources */, - CC2F65EF1E5FFB1600DA57C9 /* ASMutableElementMap.m in Sources */, - B35062541B010EFD0018CF92 /* ASImageNode+CGExtras.m in Sources */, + 9CC606651D24DF9E006581A0 /* NSIndexSet+ASHelpers.mm in Sources */, + CC0F885F1E4280B800576FED /* _ASCollectionViewCell.mm in Sources */, + CC2F65EF1E5FFB1600DA57C9 /* ASMutableElementMap.mm in Sources */, + B35062541B010EFD0018CF92 /* ASImageNode+CGExtras.mm in Sources */, E58E9E4A1E941DA5004CFC59 /* ASCollectionLayout.mm in Sources */, 6947B0C01E36B4E30007C478 /* ASStackUnpositionedLayout.mm in Sources */, - 68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.m in Sources */, - E5855DEF1EBB4D83003639AE /* ASCollectionLayoutDefines.m in Sources */, + 68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.mm in Sources */, + E5855DEF1EBB4D83003639AE /* ASCollectionLayoutDefines.mm in Sources */, B35062031B010EFD0018CF92 /* ASImageNode.mm in Sources */, - 690BC8C220F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.m in Sources */, + 690BC8C220F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.mm in Sources */, 254C6B821BF94F8A003EC431 /* ASTextKitComponents.mm in Sources */, 34EFC7601B701C8B00AD841F /* ASInsetLayoutSpec.mm in Sources */, - AC6145441D8AFD4F003D62A2 /* ASSection.m in Sources */, + AC6145441D8AFD4F003D62A2 /* ASSection.mm in Sources */, E5775AFE1F13CF7400CAC9BC /* _ASCollectionGalleryLayoutItem.mm in Sources */, - 34EFC75E1B701BF000AD841F /* ASInternalHelpers.m in Sources */, + 34EFC75E1B701BF000AD841F /* ASInternalHelpers.mm in Sources */, 34EFC7681B701CDE00AD841F /* ASLayout.mm in Sources */, DECBD6EA1BE56E1900CF4905 /* ASButtonNode.mm in Sources */, - CCCCCCE01EC3EF060087FE10 /* ASTextRunDelegate.m in Sources */, - CCCCCCDA1EC3EF060087FE10 /* ASTextLayout.m in Sources */, - CCEDDDD1200C488000FFCD0A /* ASConfiguration.m in Sources */, - 254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.m in Sources */, + CCCCCCE01EC3EF060087FE10 /* ASTextRunDelegate.mm in Sources */, + CCCCCCDA1EC3EF060087FE10 /* ASTextLayout.mm in Sources */, + CCEDDDD1200C488000FFCD0A /* ASConfiguration.mm in Sources */, + 254C6B841BF94F8A003EC431 /* ASTextNodeWordKerner.mm in Sources */, E5E2D7301EA780DF005C24C6 /* ASCollectionGalleryLayoutDelegate.mm in Sources */, 34EFC76B1B701CEB00AD841F /* ASLayoutSpec.mm in Sources */, CC3B20861C3F76D600798563 /* ASPendingStateController.mm in Sources */, 254C6B8C1BF94F8A003EC431 /* ASTextKitTailTruncater.mm in Sources */, - 6907C25A1DC4ECFE00374C66 /* ASObjectDescriptionHelpers.m in Sources */, + 6907C25A1DC4ECFE00374C66 /* ASObjectDescriptionHelpers.mm in Sources */, B35062051B010EFD0018CF92 /* ASMultiplexImageNode.mm in Sources */, - B35062251B010EFD0018CF92 /* ASMutableAttributedStringBuilder.m in Sources */, + B35062251B010EFD0018CF92 /* ASMutableAttributedStringBuilder.mm in Sources */, B35062071B010EFD0018CF92 /* ASNetworkImageNode.mm in Sources */, 34EFC76D1B701CF100AD841F /* ASOverlayLayoutSpec.mm in Sources */, - 044285101BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.m in Sources */, - CCCCCCDE1EC3EF060087FE10 /* ASTextAttribute.m in Sources */, - CCA282B51E9EA7310037E8B7 /* ASTipsController.m in Sources */, + 044285101BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.mm in Sources */, + CCCCCCDE1EC3EF060087FE10 /* ASTextAttribute.mm in Sources */, + CCA282B51E9EA7310037E8B7 /* ASTipsController.mm in Sources */, B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */, - 0442850A1BAA63FE00D16268 /* ASBatchFetching.m in Sources */, - CC35CEC420DD7F600006448D /* ASCollections.m in Sources */, - 68FC85E61CE29B9400EDD713 /* ASNavigationController.m in Sources */, - CC4C2A791D88E3BF0039ACAB /* ASTraceEvent.m in Sources */, + 0442850A1BAA63FE00D16268 /* ASBatchFetching.mm in Sources */, + CC35CEC420DD7F600006448D /* ASCollections.mm in Sources */, + 68FC85E61CE29B9400EDD713 /* ASNavigationController.mm in Sources */, + CC4C2A791D88E3BF0039ACAB /* ASTraceEvent.mm in Sources */, 34EFC76F1B701CF700AD841F /* ASRatioLayoutSpec.mm in Sources */, 254C6B8B1BF94F8A003EC431 /* ASTextKitShadower.mm in Sources */, 254C6B851BF94F8A003EC431 /* ASTextKitAttributes.mm in Sources */, 90FC784F1E4BFE1B00383C5A /* ASDisplayNode+Yoga.mm in Sources */, - CCA282C91E9EB64B0037E8B7 /* ASDisplayNodeTipState.m in Sources */, - 509E68601B3AED8E009B9150 /* ASScrollDirection.m in Sources */, + CCA282C91E9EB64B0037E8B7 /* ASDisplayNodeTipState.mm in Sources */, + 509E68601B3AED8E009B9150 /* ASScrollDirection.mm in Sources */, B35062091B010EFD0018CF92 /* ASScrollNode.mm in Sources */, 69BCE3D91EC6513B007DCCAD /* ASDisplayNode+Layout.mm in Sources */, 8BDA5FC81CDBDF95007D13B2 /* ASVideoPlayerNode.mm in Sources */, - E54E81FD1EB357BD00FFE8E1 /* ASPageTable.m in Sources */, + E54E81FD1EB357BD00FFE8E1 /* ASPageTable.mm in Sources */, 34EFC7721B701D0300AD841F /* ASStackLayoutSpec.mm in Sources */, 7AB338661C55B3420055FDE8 /* ASRelativeLayoutSpec.mm in Sources */, - CC7AF198200DAB2200A21BDE /* ASExperimentalFeatures.m in Sources */, - E5B2252E1F17E521001E1431 /* ASDispatch.m in Sources */, + CC7AF198200DAB2200A21BDE /* ASExperimentalFeatures.mm in Sources */, + E5B2252E1F17E521001E1431 /* ASDispatch.mm in Sources */, 696F01EE1DD2AF450049FBD5 /* ASEventLog.mm in Sources */, - 9C70F2051CDA4F06007D6C76 /* ASTraitCollection.m in Sources */, - 83A7D95B1D44547700BF333E /* ASWeakMap.m in Sources */, - CC034A0A1E60BEB400626263 /* ASDisplayNode+Convenience.m in Sources */, - E58E9E431E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.m in Sources */, + 9C70F2051CDA4F06007D6C76 /* ASTraitCollection.mm in Sources */, + 83A7D95B1D44547700BF333E /* ASWeakMap.mm in Sources */, + CC034A0A1E60BEB400626263 /* ASDisplayNode+Convenience.mm in Sources */, + E58E9E431E941D74004CFC59 /* ASCollectionFlowLayoutDelegate.mm in Sources */, DE84918E1C8FFF9F003D89E9 /* ASRunLoopQueue.mm in Sources */, - 68FC85E51CE29B7E00EDD713 /* ASTabBarController.m in Sources */, - CCCCCCDC1EC3EF060087FE10 /* ASTextLine.m in Sources */, + 68FC85E51CE29B7E00EDD713 /* ASTabBarController.mm in Sources */, + CCCCCCDC1EC3EF060087FE10 /* ASTextLine.mm in Sources */, 34EFC7741B701D0A00AD841F /* ASAbsoluteLayoutSpec.mm in Sources */, 1A6C000E1FAB4E2100D05926 /* ASCornerLayoutSpec.mm in Sources */, - CCCCCCE81EC3F0FC0087FE10 /* NSAttributedString+ASText.m in Sources */, + CCCCCCE81EC3F0FC0087FE10 /* NSAttributedString+ASText.mm in Sources */, 690C35621E055C5D00069B91 /* ASDimensionInternal.mm in Sources */, 909C4C761F09C98B00D6B76F /* ASTextNode2.mm in Sources */, - 68C2155A1DE10D330019C4BC /* ASCollectionViewLayoutInspector.m in Sources */, - DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.m in Sources */, + 68C2155A1DE10D330019C4BC /* ASCollectionViewLayoutInspector.mm in Sources */, + DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.mm in Sources */, B350620B1B010EFD0018CF92 /* ASTableView.mm in Sources */, B350620E1B010EFD0018CF92 /* ASTextNode.mm in Sources */, - 68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */, - CC034A141E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.m in Sources */, - 509E68661B3AEDD7009B9150 /* CoreGraphics+ASConvenience.m in Sources */, - 254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.m in Sources */, - 34566CB31BC1213700715E6B /* ASPhotosFrameworkImageRequest.m in Sources */, - 254C6B831BF94F8A003EC431 /* ASTextKitCoreTextAdditions.m in Sources */, - CCCCCCE21EC3EF060087FE10 /* ASTextUtilities.m in Sources */, - CC55A70E1E529FA200594372 /* UIResponder+AsyncDisplayKit.m in Sources */, + 68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.mm in Sources */, + CC034A141E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.mm in Sources */, + 254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.mm in Sources */, + 34566CB31BC1213700715E6B /* ASPhotosFrameworkImageRequest.mm in Sources */, + 254C6B831BF94F8A003EC431 /* ASTextKitCoreTextAdditions.mm in Sources */, + CCCCCCE21EC3EF060087FE10 /* ASTextUtilities.mm in Sources */, + CC55A70E1E529FA200594372 /* UIResponder+AsyncDisplayKit.mm in Sources */, CC56013C1F06E9A700DC4FBE /* ASIntegerMap.mm in Sources */, 697796611D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm in Sources */, - B350623B1B010EFD0018CF92 /* NSMutableAttributedString+TextKitAdditions.m in Sources */, - CCA282CD1E9EB73E0037E8B7 /* ASTipNode.m in Sources */, - CC84C7F320474C5300A3851B /* ASCGImageBuffer.m in Sources */, - 044284FD1BAA365100D16268 /* UICollectionViewLayout+ASConvenience.m in Sources */, - CC0F885B1E42807F00576FED /* ASCollectionViewFlowLayoutInspector.m in Sources */, - 690ED5981E36D118000627C0 /* ASControlNode+tvOS.m in Sources */, + B350623B1B010EFD0018CF92 /* NSMutableAttributedString+TextKitAdditions.mm in Sources */, + CCA282CD1E9EB73E0037E8B7 /* ASTipNode.mm in Sources */, + CC84C7F320474C5300A3851B /* ASCGImageBuffer.mm in Sources */, + 044284FD1BAA365100D16268 /* UICollectionViewLayout+ASConvenience.mm in Sources */, + CC0F885B1E42807F00576FED /* ASCollectionViewFlowLayoutInspector.mm in Sources */, + 690ED5981E36D118000627C0 /* ASControlNode+tvOS.mm in Sources */, 254C6B8A1BF94F8A003EC431 /* ASTextKitRenderer+TextChecking.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/CHANGELOG.md b/CHANGELOG.md index 85b2f08433..e4b300da5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,218 +1,625 @@ -## master -* Add your own contributions to the next release on the line below this with your name. -- [ASPhotosFrameworkImageRequestTests] Guard photo library with macro for tests. [Max Wang](https://github.com/wsdwsd0829). [#1147](https://github.com/TextureGroup/Texture/pull/1147) -- [ASDisplayNode] Do not cancel display when in exit hierarchy but let interface state changing to handle it. [Max Wang](https://github.com/wsdwsd0829). [#1110](https://github.com/TextureGroup/Texture/pull/1110) -- [Breaking][ASDisplayNode] Make interface state delegate protocol required. [Max Wang](https://github.com/wsdwsd0829). [#1112](https://github.com/TextureGroup/Texture/pull/1112) -- [ASCollectionView] Fix reording of cells manually for iOS 9 & 10. [Max Wang](https://github.com/wsdwsd0829). [#1081](https://github.com/TextureGroup/Texture/pull/1081) -- [ASDisplayNode] Allow add/remove interface state delegates on background thread. [Max Wang](https://github.com/wsdwsd0829). [#1090](https://github.com/TextureGroup/Texture/pull/1090) -- [License] Simplify the Texture license to be pure Apache 2 (removing ASDK-Licenses).[Scott Goodson](https://github.com/appleguy) [#1077](https://github.com/TextureGroup/Texture/pull/1077) -- [ASNetworkImageNode] Allow delegate methods to be called on background thread. [Max Wang](https://github.com/wsdwsd0829). [#1007](https://github.com/TextureGroup/Texture/pull/1007) -- [ASLayoutTransition] Add support for preserving order after node moves during transitions. (This order defines the z-order as well.) [Kevin Smith](https://github.com/wiseoldduck) [#1006] -- [ASDisplayNode] Adds support for multiple interface state delegates. [Garrett Moon](https://github.com/garrettmoon) [#979](https://github.com/TextureGroup/Texture/pull/979) -- [ASDataController] Add capability to renew supplementary views (update map) when size change from zero to non-zero.[Max Wang](https://github.com/wsdwsd0829) [#842](https://github.com/TextureGroup/Texture/pull/842) -- Make `ASPerformMainThreadDeallocation` visible in C. [Adlai Holler](https://github.com/Adlai-Holler) -- Add snapshot test for astextnode2. [Max Wang](https://github.com/wsdwsd0829) [#935](https://github.com/TextureGroup/Texture/pull/935) -- Internal housekeeping on the async transaction (rendering) system. [Adlai Holler](https://github.com/Adlai-Holler) -- Add new protocol `ASLocking` that extends `NSLocking` with `tryLock`, and allows taking multiple locks safely. [Adlai Holler](https://github.com/Adlai-Holler) -- Make the main thread ivar deallocation system available to other classes. Plus a little optimization. See `ASMainThreadDeallocation.h`. [Adlai Holler](https://github.com/Adlai-Holler) [#959](https://github.com/TextureGroup/Texture/pull/959) -- Reduce usage of autorelease pools. [Adlai Holler](https://github.com/Adlai-Holler) [#968](https://github.com/TextureGroup/Texture/pull/968) -- Clean up unused/unneeded header macros. [Adlai Holler](https://github.com/Adlai-Holler) -- Clean up C-function `extern` decorators. [Adlai Holler](https://github.com/Adlai-Holler) -- Add an experiment to reduce work involved in collection teardown. [Adlai Holler](https://github.com/Adlai-Holler) -- Optimize layout flattening, particularly reducing retain/release operations. [Adlai Holler](https://github.com/Adlai-Holler) -- Create a method to transfer strong C-arrays into immutable NSArrays, reducing retain/release traffic. [Adlai Holler](https://github.com/Adlai-Holler) -- Remove yoga layout spec, which has been superseded by tighter Yoga integration (`ASDisplayNode+Yoga.h`) -- Properly consider node for responder methods [Michael Schneider](https://github.com/maicki) -- Introduce let / var macros and some further cleanup. [Michael Schneider](https://github.com/maicki) [#1012](https://github.com/TextureGroup/Texture/pull/1012) -- [IGListKit] Adds missing UIScrollViewDelegate method to DataSource proxy [Sergey Pronin](https://github.com/wannabehero) -- Fix misleading/scary stack trace shown when an assertion occurs during node measurement [Huy Nguyen](https://github.com/nguyenhuy) [#1022](https://github.com/TextureGroup/Texture/pull/1022) -- Fix build on 32-bit simulator in Xcode 9.3 and later, caused by `Thread-local storage is not supported on this architecture.` [Adlai Holler](https://github.com/Adlai-Holler) -- Enable locking assertions (and add some more) to improve and enforce locking safety within the framework [Huy Nguyen](https://github.com/nguyenhuy) [#1024](https://github.com/TextureGroup/Texture/pull/1024) -- Split MapKit, Photos, and AssetsLibrary dependent code into separate subspecs to improve binary size and start time when they're not needed. The default subspec includes all three for backwards compatibility, but this **will change in 3.0**. When using non-Cocoapods build environments, define `AS_USE_PHOTOS, AS_USE_MAPKIT, AS_USE_ASSETS_LIBRARY` to 1 respectively to signal their use. [Adlai Holler](https://github.com/Adlai-Holler) -- Optimization: Removed an NSMutableArray in flattened layouts. [Adlai Holler](https://github.com/Adlai-Holler) -- Reduced binary size by disabling exception support (which we don't use.) [Adlai Holler](https://github.com/Adlai-Holler) -- Create and set delegate for clip corner layers within ASDisplayNode [Michael Schneider](https://github.com/maicki) [#1029](https://github.com/TextureGroup/Texture/pull/1029) -- Improve locking situation in ASVideoPlayerNode [Michael Schneider](https://github.com/maicki) [#1042](https://github.com/TextureGroup/Texture/pull/1042) -- Optimize ASDisplayNode -> ASNodeController reference by removing weak proxy and objc associated objects. [Adlai Holler](https://github.com/Adlai-Holler) -- Remove CA transaction signpost injection because it causes more transactions and is too chatty. [Adlai Holler](https://github.com/Adlai-Holler) -- Optimize display node accessibility by not creating attributed & non-attributed copies of hint, label, and value. [Adlai Holler](https://github.com/Adlai-Holler) -- Add an experimental feature that reuses CTFramesetter objects in ASTextNode2 to improve performance. [Adlai Holler](https://github.com/Adlai-Holler) -- Add NS_DESIGNATED_INITIALIZER to ASViewController initWithNode: [Michael Schneider](https://github.com/maicki) [#1054](https://github.com/TextureGroup/Texture/pull/1054) -- Optimize text stack by removing unneeded copying. [Adlai Holler](https://github.com/Adlai-Holler) -- Renamed `accessibleElements` to `accessibilityElements` and removed the re-definition of the property in ASDisplayView. [Jia Wern Lim](https://github.com/jiawernlim) -- Remove double scaling of lineHeightMultiple & paragraphSpacing attributes in ASTextKitFontSizeAdjuster. [Eric Jensen](https://github.com/ejensen) -- Add a delegate callback for when the framework has initialized. [Adlai Holler](https://github.com/Adlai-Holler) -- Improve TextNode2 by skipping an unneeded copy during measurement. [Adlai Holler](https://github.com/Adlai-Holler) -- Improve locking around clearContents [Michael Schneider](https://github.com/maicki) -- Unlock before cleanup and calling out to subclass hooks for animated images. [Michael Schneider](https://github.com/maicki) [#1087](https://github.com/TextureGroup/Texture/pull/1087) -- [ASDisplayNode] Fix interface state update for layer backed nodes when layer thrashes (interface coaleascing case).[Max Wang](https://github.com/wsdwsd0829). [#1111](https://github.com/TextureGroup/Texture/pull/1111) -- [ASPINRemoteImageManager] Add a new API for setting a preconfigured PINRemoteImageManager. [Ernest Ma](https://github.com/ernestmama) [#1124](https://github.com/TextureGroup/Texture/pull/1124) -- Small optimization to the layout spec & yoga layout systems by eliminating array copies. [Adlai Holler](https://github.com/Adlai-Holler) -- Optimize layout process by removing `ASRectMap`. [Adlai Holler](https://github.com/Adlai-Holler) -- Remove necessity to use view to access rangeController in ASTableNode, ASCollectionNode. [Michael Schneider](https://github.com/maicki) -- Remove display node's reliance on shared_ptr. [Adlai Holler](https://github.com/Adlai-Holler) -- [ASCollectionView] Fix a crash that is caused by clearing a collection view's data while it's still being used. [Huy Nguyen](https://github.com/nguyenhuy) [#1154](https://github.com/TextureGroup/Texture/pull/1154) -- Clean up timing of layout tree flattening/ copying of unflattened tree for Weaver. [Michael Zuccarino](https://github.com/mikezucc) [#1157](https://github.com/TextureGroup/Texture/pull/1157) +# Change Log -## 2.7 -- Fix pager node for interface coalescing. [Max Wang](https://github.com/wsdwsd0829) [#877](https://github.com/TextureGroup/Texture/pull/877) -- [ASTextNode2] Upgrade lock safety by protecting all ivars (including rarely-changed ones). -- User FLT_EPSILON in ASCeilPixelValue and ASFloorPixelValue to help with floating point precision errors when computing layouts for 3x devices. [Ricky Cancro](https://github.com/rcancro) [#838](https://github.com/TextureGroup/Texture/pull/864) -- Disable interface colescing and match to pre-colescing interface update behavior [Max Wang](https://github.com/wsdwsd0829) [#862](https://github.com/TextureGroup/Texture/pull/862) -- [ASDisplayNode] Add safeAreaInsets, layoutMargins and related properties to ASDisplayNode, with full support for older OS versions [Yevgen Pogribnyi](https://github.com/ypogribnyi) [#685](https://github.com/TextureGroup/Texture/pull/685) -- [ASPINRemoteImageDownloader] Allow cache to provide animated image. [Max Wang](https://github.com/wsdwsd0829) [#850](https://github.com/TextureGroup/Texture/pull/850) -- [tvOS] Fixes errors when building against tvOS SDK [Alex Hill](https://github.com/alexhillc) [#728](https://github.com/TextureGroup/Texture/pull/728) -- [ASDisplayNode] Add unit tests for layout z-order changes (with an open issue to fix). -- [ASWrapperCellNode] Introduce a new class allowing more control of UIKit passthrough cells. -- [ASDisplayNode] Consolidate main thread initialization and allow apps to invoke it manually instead of +load. -- [ASRunloopQueue] Introduce new runloop queue(ASCATransactionQueue) to coalesce Interface state update calls for view controller transitions. -- [ASRangeController] Fix stability of "minimum" rangeMode if the app has more than one layout before scrolling. -- **Important** ASDisplayNode's cornerRadius is a new thread-safe bridged property that should be preferred over CALayer's. Use the latter at your own risk! [Huy Nguyen](https://github.com/nguyenhuy) [#749](https://github.com/TextureGroup/Texture/pull/749). -- [ASCellNode] Adds mapping for UITableViewCell focusStyle [Alex Hill](https://github.com/alexhillc) [#727](https://github.com/TextureGroup/Texture/pull/727) -- [ASNetworkImageNode] Fix capturing self in the block while loading image in ASNetworkImageNode. [Denis Mororozov](https://github.com/morozkin) [#777](https://github.com/TextureGroup/Texture/pull/777) -- [ASTraitCollection] Add new properties of UITraitCollection to ASTraitCollection. [Yevgen Pogribnyi](https://github.com/ypogribnyi) -- [ASRectMap] Replace implementation of ASRectTable with a simpler one based on unordered_map.[Scott Goodson](https://github.com/appleguy) [#719](https://github.com/TextureGroup/Texture/pull/719) -- [ASCollectionView] Add missing flags for ASCollectionDelegate [Ilya Zheleznikov](https://github.com/ilyailya) [#718](https://github.com/TextureGroup/Texture/pull/718) -- [ASNetworkImageNode] Deprecates .URLs in favor of .URL [Garrett Moon](https://github.com/garrettmoon) [#699](https://github.com/TextureGroup/Texture/pull/699) -- [iOS11] Update project settings and fix errors [Eke](https://github.com/Eke) [#676](https://github.com/TextureGroup/Texture/pull/676) -- [ASCornerLayoutSpec] New layout spec class for declarative corner element layout. [#657](https://github.com/TextureGroup/Texture/pull/657) [huangkun](https://github.com/huang-kun) -- [ASDisplayNode layout] Fix an issue that causes a pending layout to be applied multiple times. [Huy Nguyen](https://github.com/nguyenhuy) [#695](https://github.com/TextureGroup/Texture/pull/695) -- [ASDisplayNode layout] Fix an issue that sometimes causes a node's pending layout to not be applied. [Huy Nguyen](https://github.com/nguyenhuy) [#792](https://github.com/TextureGroup/Texture/pull/792) -- [ASScrollNode] Ensure the node respects the given size range while calculating its layout. [#637](https://github.com/TextureGroup/Texture/pull/637) [Huy Nguyen](https://github.com/nguyenhuy) -- [ASScrollNode] Invalidate the node's calculated layout if its scrollable directions changed. Also add unit tests for the class. [#637](https://github.com/TextureGroup/Texture/pull/637) [Huy Nguyen](https://github.com/nguyenhuy) -- Add new unit testing to the layout engine. [Adlai Holler](https://github.com/Adlai-Holler) [#424](https://github.com/TextureGroup/Texture/pull/424) -- [Automatic Subnode Management] Nodes with ASM enabled now insert/delete their subnodes as soon as they enter preload state, so subnodes can start preloading right away. [Huy Nguyen](https://github.com/nguyenhuy) [#706](https://github.com/TextureGroup/Texture/pull/706) -- [ASCollectionNode] Added support for interactive item movement. [Adlai Holler](https://github.com/Adlai-Holler) -- Added an experimental "no-copy" rendering API. See ASGraphicsContext.h for info. [Adlai Holler](https://github.com/Adlai-Holler) -- Dropped support for iOS 8. [Adlai Holler](https://github.com/Adlai-Holler) -- Added a configuration API – a unified place to turn on/off experimental Texture features. See `ASConfiguration.h` for info. [Adlai Holler](https://github.com/Adlai-Holler) -- **Breaking** Changes to ASNetworkImageNode: [Adlai Holler](https://github.com/Adlai-Holler) - - Modified `ASImageDownloaderCompletion` to add an optional `id userInfo` field. Your custom downloader can pass `nil`. - - Modified the last argument to `-[ASNetworkImageNodeDelegate imageNode:didLoadImage:info:]` method from a struct to an object of new class `ASNetworkImageLoadInfo` which includes other metadata about the load operation. -- Removed +load static initializer from ASDisplayNode. [Adlai Holler](https://github.com/Adlai-Holler) -- Optimized ASNetworkImageNode loading and resolved edge cases where the image provided to the delegate was not the image that was loaded. [Adlai Holler](https://github.com/Adlai-Holler) [#778](https://github.com/TextureGroup/Texture/pull/778/) -- Make `ASCellNode` tint color apply to table view cell accessories. [Vladyslav Chapaev](https://github.com/ShogunPhyched) [#764](https://github.com/TextureGroup/Texture/pull/764) -- Fix ASTextNode2 is accessing backgroundColor off main while sizing / layout is happening. [Michael Schneider](https://github.com/maicki) [#794](https://github.com/TextureGroup/Texture/pull/778/) -- Pass scrollViewWillEndDragging delegation through in ASIGListAdapterDataSource for IGListKit integration. [#796](https://github.com/TextureGro -- up/Texture/pull/796) -- Fix UIResponder handling with view backing ASDisplayNode. [Michael Schneider](https://github.com/maicki) [#789](https://github.com/TextureGroup/Texture/pull/789/) -- Optimized thread-local storage by replacing pthread_specific with C11 thread-local variables. [Adlai Holler](https://github.com/Adlai-Holler) [#811](https://github.com/TextureGroup/Texture/pull/811/) -- Fixed a thread-sanitizer warning in ASTextNode. [Adlai Holler](https://github.com/Adlai-Holler) [#830](https://github.com/TextureGroup/Texture/pull/830/) -- Fix ASTextNode2 handling background color incorrectly. [Adlai Holler](https://github.com/Adlai-Holler) [#831](https://github.com/TextureGroup/Texture/pull/831/) -- [NoCopyRendering] Improved performance & fixed image memory not being tagged in Instruments. [Adlai Holler](https://github.com/Adlai-Holler) [#833](https://github.com/TextureGroup/Texture/pull/833/) -- Use `NS_RETURNS_RETAINED` macro to make our methods a tiny bit faster. [Adlai Holler](https://github.com/Adlai-Holler) [#843](https://github.com/TextureGroup/Texture/pull/843/) -- `ASDisplayNode, ASLayoutSpec, and ASLayoutElementStyle` now conform to `NSLocking`. They act as recursive locks. Useful locking macros have been added as `ASThread.h`. Subclasses / client code can lock these objects but should be careful as usual when dealing with locks. [Adlai Holler](https://github.com/Adlai-Holler) -- Introduces `ASRecursiveUnfairLock` as an experiment to improve locking performance. [Adlai Holler](https://github.com/Adlai-Holler) -- Adds an experiment to shorten init time. [Adlai Holler](https://github.com/Adlai-Holler) -- Adds a check that Texture is compiled with stdc++11 as specified by the podfile. gnu++11 can cause subtle issues that are currently being investigated. [Adlai Holler](https://github.com/Adlai-Holler) -- Adds an experiment to call ASNetworkImageNode callbacks off main. [Garrett Moon](https://github.com/garrettmoon) -- Prevent UITextView from updating contentOffset while deallocating [Michael Schneider](https://github.com/maicki) -- [ASCollectionNode/ASTableNode] Fix a crash occurs while remeasuring cell nodes. [Huy Nguyen](https://github.com/nguyenhuy) [#917](https://github.com/TextureGroup/Texture/pull/917) -- Fix an issue where ASConfigurationDelegate would not call out for "control" users. If set, it now receives events whenever an experimental feature decision point occurs, whether it's enabled or not. [Adlai Holler](https://github.com/Adlai-Holler) -- [ASDisplayNode] Fix an issue that causes a node to sometimes return an outdated calculated size or size range. [Huy Nguyen](https://github.com/nguyenhuy) [#808](https://github.com/TextureGroup/Texture/pull/808) -- Add an experimental deallocation queue implementation that's more efficient. [Adlai Holler](https://github.com/Adlai-Holler) -- Standardize property declaration style. [Adlai Holler](https://github.com/Adlai-Holler) -- [ASTableView] Fix an issue that causes table view to use one of a cell's invalid layouts instead of generating a new one. [Huy Nguyen](https://github.com/nguyenhuy) [#942](https://github.com/TextureGroup/Texture/pull/942) +## [2.8](https://github.com/TextureGroup/Texture/tree/2.8) (2018-11-04) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.7...2.8) -## 2.6 -- [Xcode 9] Updated to require Xcode 9 (to fix warnings) [Garrett Moon](https://github.com/garrettmoon) -- [ASCollectionView] Improve performance and behavior of rotation / bounds changes. [Scott Goodson](https://github.com/appleguy) [#431](https://github.com/TextureGroup/Texture/pull/431) -- [ASCollectionView] Improve index space translation of Flow Layout Delegate methods. [Scott Goodson](https://github.com/appleguy) -- [Animated Image] Adds support for animated WebP as well as improves GIF handling. [#605](https://github.com/TextureGroup/Texture/pull/605) [Garrett Moon](https://github.com/garrettmoon) -- [ASCollectionView] Check if batch fetching is needed if batch fetching parameter has been changed. [#624](https://github.com/TextureGroup/Texture/pull/624) [Garrett Moon](https://github.com/garrettmoon) -- [ASNetworkImageNode] New delegate callback to tell the consumer whether the image was loaded from cache or download. [Adlai Holler](https://github.com/Adlai-Holler) -- [Layout] Fixes a deadlock in layout. [#638](https://github.com/TextureGroup/Texture/pull/638) [Garrett Moon](https://github.com/garrettmoon) -- Updated to be backwards compatible with Xcode 8. [Adlai Holler](https://github.com/Adlai-Holler) -- [API CHANGES] `ASPerformMainThreadDeallocation` and `ASPerformBackgroundDeallocation` functions take `id *` instead of `id` and they're now more reliable. Also, in Swift, `ASDeallocQueue.sharedDeallocationQueue() -> ASDeallocQueue.sharedDeallocationQueue`. [Adlai Holler](https://github.com/Adlai-Holler) [#651](https://github.com/TextureGroup/Texture/pull/651) -- [Collection/Table] Added direct support for mapping section indexes between data spaces. [Adlai Holler](https://github.com/Adlai-Holler) [#651](https://github.com/TextureGroup/Texture/pull/660) +**Merged pull requests:** -## 2.5.1 -- [ASVideoNode] Fix unreleased time observer. [Flo Vouin](https://github.com/flovouin) -- [PINCache] Set a default .byteLimit to reduce disk usage and startup time. [#595](https://github.com/TextureGroup/Texture/pull/595) [Scott Goodson](https://github.com/appleguy) -- [ASNetworkImageNode] Fix deadlock in GIF handling. [#582](https://github.com/TextureGroup/Texture/pull/582) [Garrett Moon](https://github.com/garrettmoon) -- [ASDisplayNode] Add attributed versions of a11y label, hint and value. [#554](https://github.com/TextureGroup/Texture/pull/554) [Alexander Hüllmandel](https://github.com/fruitcoder) -- [ASCornerRounding] Introduce .cornerRoundingType: CALayer, Precomposited, or Clip Corners. [Scott Goodson](https://github.com/appleguy) [#465](https://github.com/TextureGroup/Texture/pull/465) -- [Yoga] Add insertYogaNode:atIndex: method. Improve handling of relayouts. [Scott Goodson](https://github.com/appleguy) +- Add -Wno-implicit-retain-self to podspec + smaller cleanups \#trivial [\#1209](https://github.com/TextureGroup/Texture/pull/1209) ([maicki](https://github.com/maicki)) +- Address compiler warnings \#trivial [\#1207](https://github.com/TextureGroup/Texture/pull/1207) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Convert the codebase to Objective-C++ [\#1206](https://github.com/TextureGroup/Texture/pull/1206) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add tests for accessibility [\#1205](https://github.com/TextureGroup/Texture/pull/1205) ([wiseoldduck](https://github.com/wiseoldduck)) +- Revert \#1023 \#trivial [\#1204](https://github.com/TextureGroup/Texture/pull/1204) ([maicki](https://github.com/maicki)) +- Follow up cleanup \#trivial [\#1203](https://github.com/TextureGroup/Texture/pull/1203) ([maicki](https://github.com/maicki)) +- Add experiment flag to skip layoutIfNeeded in enterPreloadState for ASM nodes \#trivial [\#1201](https://github.com/TextureGroup/Texture/pull/1201) ([maicki](https://github.com/maicki)) +- Fix logic cleaning data if delegate / dataSource changes and bring over logic to ASTableView [\#1200](https://github.com/TextureGroup/Texture/pull/1200) ([maicki](https://github.com/maicki)) +- Tweak a11y label aggregation behavior to enable container label overrides [\#1199](https://github.com/TextureGroup/Texture/pull/1199) ([maicki](https://github.com/maicki)) +- Fix shadowed var warning \(and add clarity\) \#trivial [\#1198](https://github.com/TextureGroup/Texture/pull/1198) ([wiseoldduck](https://github.com/wiseoldduck)) +- Allow configuring imageCache when initializing ASPINRemoteImageDownloader. [\#1197](https://github.com/TextureGroup/Texture/pull/1197) ([wiseoldduck](https://github.com/wiseoldduck)) +- ASTextNode2 to consider both width and height when determining if it is calculating an intrinsic size [\#1196](https://github.com/TextureGroup/Texture/pull/1196) ([ernestmama](https://github.com/ernestmama)) +- Remove extraneous ";" \#trivial [\#1194](https://github.com/TextureGroup/Texture/pull/1194) ([wiseoldduck](https://github.com/wiseoldduck)) +- Newline character support and truncated line sizing improvement. [\#1193](https://github.com/TextureGroup/Texture/pull/1193) ([wiseoldduck](https://github.com/wiseoldduck)) +- Correct linePositionModifier behavior [\#1192](https://github.com/TextureGroup/Texture/pull/1192) ([maicki](https://github.com/maicki)) +- Move AS\_TEXT\_ALERT\_UNIMPLEMENTED\_FEATURE into ASTextNodeCommon \#trivial [\#1191](https://github.com/TextureGroup/Texture/pull/1191) ([maicki](https://github.com/maicki)) +- A11y for scrollnode [\#1188](https://github.com/TextureGroup/Texture/pull/1188) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Yoga integration improvements [\#1187](https://github.com/TextureGroup/Texture/pull/1187) ([maicki](https://github.com/maicki)) +- Remove unnecessary ASWeakProxy import \#trivial [\#1186](https://github.com/TextureGroup/Texture/pull/1186) ([maicki](https://github.com/maicki)) +- Directly use \_\_instanceLock\_\_ to lock / unlock without having to create and destroy a MutextUnlocker \#trivial [\#1185](https://github.com/TextureGroup/Texture/pull/1185) ([maicki](https://github.com/maicki)) +- Don’t handle touches on additional attributed message if passthrough is enabled [\#1184](https://github.com/TextureGroup/Texture/pull/1184) ([maicki](https://github.com/maicki)) +- Set the default values for showsVerticalScrollIndicator and showsHorizontalScrollIndicator \#trivial [\#1181](https://github.com/TextureGroup/Texture/pull/1181) ([maicki](https://github.com/maicki)) +- Move import of stdatomic to ASRecursiveUnfairLock implementation file \#trivial [\#1180](https://github.com/TextureGroup/Texture/pull/1180) ([maicki](https://github.com/maicki)) +- Add NSLocking conformance to ASNodeController [\#1179](https://github.com/TextureGroup/Texture/pull/1179) ([maicki](https://github.com/maicki)) +- Only initialize framework once, avoid multiple across tests \#trivial [\#1178](https://github.com/TextureGroup/Texture/pull/1178) ([maicki](https://github.com/maicki)) +- Expose a way to determine if a text node will truncate for a given constrained size \#trivial [\#1177](https://github.com/TextureGroup/Texture/pull/1177) ([maicki](https://github.com/maicki)) +- Fix define spaces \#trivial [\#1176](https://github.com/TextureGroup/Texture/pull/1176) ([maicki](https://github.com/maicki)) +- Expose test\_resetWithConfiguration: for testing \#trivial [\#1175](https://github.com/TextureGroup/Texture/pull/1175) ([maicki](https://github.com/maicki)) +- Add way to suppress invalid CollectionUpdateExceptions \#trivial [\#1173](https://github.com/TextureGroup/Texture/pull/1173) ([maicki](https://github.com/maicki)) +- Use interface state to manage image loading \#trivial [\#1172](https://github.com/TextureGroup/Texture/pull/1172) ([maicki](https://github.com/maicki)) +- ASTableNode init method match checks from ASCollectionNode [\#1171](https://github.com/TextureGroup/Texture/pull/1171) ([maicki](https://github.com/maicki)) +- \[ASDisplayNode\] Expose default Texture-set accessibility values as properties [\#1170](https://github.com/TextureGroup/Texture/pull/1170) ([jiawernlim](https://github.com/jiawernlim)) +- Fix mismatch in UIAccessibilityAction selector method [\#1169](https://github.com/TextureGroup/Texture/pull/1169) ([maicki](https://github.com/maicki)) +- Small fix in ASTextKitRenderer \#trivial [\#1167](https://github.com/TextureGroup/Texture/pull/1167) ([nguyenhuy](https://github.com/nguyenhuy)) +- ASTextNode2 to ignore certain text alignments while calculating intrinsic size [\#1166](https://github.com/TextureGroup/Texture/pull/1166) ([nguyenhuy](https://github.com/nguyenhuy)) +- Update Jekyll to 3.6.3 [\#1165](https://github.com/TextureGroup/Texture/pull/1165) ([nguyenhuy](https://github.com/nguyenhuy)) +- Migrate placeholder example project from 1.0 to 2.x [\#1164](https://github.com/TextureGroup/Texture/pull/1164) ([ay8s](https://github.com/ay8s)) +- Update documentation of ASNetworkImageNodeDelegate \#trivial [\#1163](https://github.com/TextureGroup/Texture/pull/1163) ([nguyenhuy](https://github.com/nguyenhuy)) +- Mismatch name experimental features [\#1159](https://github.com/TextureGroup/Texture/pull/1159) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Set default tuning params [\#1158](https://github.com/TextureGroup/Texture/pull/1158) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Clean up timing of layout tree flattening/ copying of unflattened tree for Weaver [\#1157](https://github.com/TextureGroup/Texture/pull/1157) ([mikezucc](https://github.com/mikezucc)) +- Only clear ASCollectionView's data during deallocation [\#1154](https://github.com/TextureGroup/Texture/pull/1154) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASTextNode2\] Add improved support for all line-break modes in experimental text node. [\#1150](https://github.com/TextureGroup/Texture/pull/1150) ([wiseoldduck](https://github.com/wiseoldduck)) +- Guard photo library with macro for tests [\#1147](https://github.com/TextureGroup/Texture/pull/1147) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Rollout ASDeallocQueueV2 \#trivial [\#1143](https://github.com/TextureGroup/Texture/pull/1143) ([ernestmama](https://github.com/ernestmama)) +- Fix crash setting attributed text on multiple threads [\#1141](https://github.com/TextureGroup/Texture/pull/1141) ([maicki](https://github.com/maicki)) +- Add missing NS\_NOESCAPE attributes in overwritten methods \#trivial [\#1139](https://github.com/TextureGroup/Texture/pull/1139) ([ejensen](https://github.com/ejensen)) +- Add missing comma in ASExperimentalFeatures \#trivial [\#1137](https://github.com/TextureGroup/Texture/pull/1137) ([nguyenhuy](https://github.com/nguyenhuy)) +- Add ASExperimentalSkipClearData \#trivial [\#1136](https://github.com/TextureGroup/Texture/pull/1136) ([maicki](https://github.com/maicki)) +- Fix RemoteImageDownloader name mismatch \#trivial [\#1134](https://github.com/TextureGroup/Texture/pull/1134) ([ernestmama](https://github.com/ernestmama)) +- Fix compilation warnings \#trivial [\#1132](https://github.com/TextureGroup/Texture/pull/1132) ([ejensen](https://github.com/ejensen)) +- Remove reliance on shared\_ptr for ASDisplayNodeLayouts [\#1131](https://github.com/TextureGroup/Texture/pull/1131) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Make yoga & layout specs faster by eliminating some copies [\#1128](https://github.com/TextureGroup/Texture/pull/1128) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove ASRectMap, which is not worth its own weight [\#1127](https://github.com/TextureGroup/Texture/pull/1127) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASPINRemoteImageDownloader\] Fix +setSharedPreconfiguredRemoteImageManager:'s doc \#trivial [\#1126](https://github.com/TextureGroup/Texture/pull/1126) ([nguyenhuy](https://github.com/nguyenhuy)) +- Add a method for setting preconfigured PINRemoteImageManager [\#1124](https://github.com/TextureGroup/Texture/pull/1124) ([ernestmama](https://github.com/ernestmama)) +- Don't copy onDidLoadBlocks \#trivial [\#1123](https://github.com/TextureGroup/Texture/pull/1123) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove use of NSHashTable for interface state delegates \#trivial [\#1122](https://github.com/TextureGroup/Texture/pull/1122) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix typos and minor code cleanups \#trivial [\#1120](https://github.com/TextureGroup/Texture/pull/1120) ([nguyenhuy](https://github.com/nguyenhuy)) +- Don't setNeedsDisplay on text node 2 measure \#trivial [\#1116](https://github.com/TextureGroup/Texture/pull/1116) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Don't copy container during ASTextNode2 measure [\#1115](https://github.com/TextureGroup/Texture/pull/1115) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Make interface state delegate non optional [\#1112](https://github.com/TextureGroup/Texture/pull/1112) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Interface state not update correctly during layer thrash. [\#1111](https://github.com/TextureGroup/Texture/pull/1111) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Fix layer backed nodes not update properly [\#1110](https://github.com/TextureGroup/Texture/pull/1110) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- changelog fix: let / var macros did not make it to 2.7 [\#1109](https://github.com/TextureGroup/Texture/pull/1109) ([jozsefmihalicza](https://github.com/jozsefmihalicza)) +- Improve locking around clearContents [\#1107](https://github.com/TextureGroup/Texture/pull/1107) ([maicki](https://github.com/maicki)) +- Add missing argument for calling image download completion block \#trivial [\#1106](https://github.com/TextureGroup/Texture/pull/1106) ([maicki](https://github.com/maicki)) +- Fix URL for blog about Pinterest [\#1105](https://github.com/TextureGroup/Texture/pull/1105) ([muukii](https://github.com/muukii)) +- Remove necessity to use view to access rangeController in ASTableNode, ASCollectionNode [\#1103](https://github.com/TextureGroup/Texture/pull/1103) ([maicki](https://github.com/maicki)) +- Add a -textureDidInitialize delegate callback [\#1100](https://github.com/TextureGroup/Texture/pull/1100) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Reuse interface state delegates when calling out \#trivial [\#1099](https://github.com/TextureGroup/Texture/pull/1099) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add an explicit cast to satisfy strict compilers \#trivial [\#1098](https://github.com/TextureGroup/Texture/pull/1098) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix a couple typos. [\#1092](https://github.com/TextureGroup/Texture/pull/1092) ([jtbthethird](https://github.com/jtbthethird)) +- \#trivial Shouldn't hold the lock while adding subnodes [\#1091](https://github.com/TextureGroup/Texture/pull/1091) ([garrettmoon](https://github.com/garrettmoon)) +- Allow to add interface state delegate in background. [\#1090](https://github.com/TextureGroup/Texture/pull/1090) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Fix Typo [\#1089](https://github.com/TextureGroup/Texture/pull/1089) ([jtbthethird](https://github.com/jtbthethird)) +- Add subnode should not be called with the lock held. \#trivial [\#1088](https://github.com/TextureGroup/Texture/pull/1088) ([garrettmoon](https://github.com/garrettmoon)) +- Unlock before cleanup and calling out to subclass hooks for animated images. [\#1087](https://github.com/TextureGroup/Texture/pull/1087) ([maicki](https://github.com/maicki)) +- Fix collection editing [\#1081](https://github.com/TextureGroup/Texture/pull/1081) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Fix compiler error in ASLocking \#trivial [\#1079](https://github.com/TextureGroup/Texture/pull/1079) ([nguyenhuy](https://github.com/nguyenhuy)) +- Update showcase to add Wishpoke [\#1078](https://github.com/TextureGroup/Texture/pull/1078) ([dhatuna](https://github.com/dhatuna)) +- \[License\] Simplify the Texture license to be pure Apache 2 \(removing ASDK-Licenses\). [\#1077](https://github.com/TextureGroup/Texture/pull/1077) ([appleguy](https://github.com/appleguy)) +- Fix multiple documentation issues \#trivial [\#1073](https://github.com/TextureGroup/Texture/pull/1073) ([maicki](https://github.com/maicki)) +- Refactored `accessibleElements` to `accessibilityElements` [\#1069](https://github.com/TextureGroup/Texture/pull/1069) ([jiawernlim](https://github.com/jiawernlim)) +- Readability improvements in ASDataController \#trivial [\#1067](https://github.com/TextureGroup/Texture/pull/1067) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove direct ivar access on non-self object to fix mocking case \#trivial [\#1066](https://github.com/TextureGroup/Texture/pull/1066) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Reduce copying in ASTextNode2 stack [\#1065](https://github.com/TextureGroup/Texture/pull/1065) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add an experimental framesetter cache in ASTextNode2 [\#1063](https://github.com/TextureGroup/Texture/pull/1063) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove extra string/attributed string creation in accessibility props [\#1062](https://github.com/TextureGroup/Texture/pull/1062) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove objc association & weak proxy from node -\> controller pointer [\#1061](https://github.com/TextureGroup/Texture/pull/1061) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove CATransaction signposts [\#1060](https://github.com/TextureGroup/Texture/pull/1060) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASTextNode2\] Simplify allocWithZone: + initialize implementation \#trivial [\#1059](https://github.com/TextureGroup/Texture/pull/1059) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASTextNode\] Fixes in ASTextKitFontSizeAdjuster [\#1056](https://github.com/TextureGroup/Texture/pull/1056) ([ejensen](https://github.com/ejensen)) +- Revert "Optimize drawing code + add examples how to round corners \(\#996\) [\#1055](https://github.com/TextureGroup/Texture/pull/1055) ([maicki](https://github.com/maicki)) +- Add NS\_DESIGNATED\_INITIALIZER to ASViewController initWithNode: [\#1054](https://github.com/TextureGroup/Texture/pull/1054) ([maicki](https://github.com/maicki)) +- Fix headers in markdown [\#1053](https://github.com/TextureGroup/Texture/pull/1053) ([Un3qual](https://github.com/Un3qual)) +- Avoid setting frame on a node's backing store while holding its lock [\#1048](https://github.com/TextureGroup/Texture/pull/1048) ([nguyenhuy](https://github.com/nguyenhuy)) +- \#trivial Add a comment about tiling mode and issue \#1046 [\#1047](https://github.com/TextureGroup/Texture/pull/1047) ([wiseoldduck](https://github.com/wiseoldduck)) +- Add documentation for rounding corners within Texture \#trivial [\#1044](https://github.com/TextureGroup/Texture/pull/1044) ([maicki](https://github.com/maicki)) +- Improve locking situation in ASVideoPlayerNode [\#1042](https://github.com/TextureGroup/Texture/pull/1042) ([maicki](https://github.com/maicki)) +- Revert unreleased layout debug method name change from \#1030 \#trivial [\#1039](https://github.com/TextureGroup/Texture/pull/1039) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Pin OCMock version to 3.4.1 because 3.4.2 has issues [\#1038](https://github.com/TextureGroup/Texture/pull/1038) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix & update ASCollectionNode constrained size doc. \#trivial [\#1037](https://github.com/TextureGroup/Texture/pull/1037) ([ay8s](https://github.com/ay8s)) +- Fix warning for ASLayout method override for the designated initializer of the superclass '-init' not found \#trivial [\#1036](https://github.com/TextureGroup/Texture/pull/1036) ([maicki](https://github.com/maicki)) +- Fix the bug I introduced in \#1030 \#trivial [\#1035](https://github.com/TextureGroup/Texture/pull/1035) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Turn off exceptions to reduce binary size \(-600KB for arm64\) [\#1033](https://github.com/TextureGroup/Texture/pull/1033) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Turn lock-checking on only when assertions are enabled \#trivial [\#1032](https://github.com/TextureGroup/Texture/pull/1032) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove NSMutableArray for retaining sublayout elements [\#1030](https://github.com/TextureGroup/Texture/pull/1030) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Create and set delegate for clip corner layers within ASDisplayNode [\#1029](https://github.com/TextureGroup/Texture/pull/1029) ([maicki](https://github.com/maicki)) +- Split framework dependencies into separate subspecs [\#1028](https://github.com/TextureGroup/Texture/pull/1028) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove misleading comment and add assertion \#trivial [\#1027](https://github.com/TextureGroup/Texture/pull/1027) ([wiseoldduck](https://github.com/wiseoldduck)) +- Address warnings in Xcode \>= 9.3 about using %zd for NSInteger \#trivial [\#1026](https://github.com/TextureGroup/Texture/pull/1026) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix 32-bit simulator build on Xcode \>= 9.3 [\#1025](https://github.com/TextureGroup/Texture/pull/1025) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Stricter locking assertions [\#1024](https://github.com/TextureGroup/Texture/pull/1024) ([nguyenhuy](https://github.com/nguyenhuy)) +- Make sure -\_completePendingLayoutTransition is called without the node's instance lock \#trivial [\#1023](https://github.com/TextureGroup/Texture/pull/1023) ([nguyenhuy](https://github.com/nguyenhuy)) +- Fix misleading/scary stack trace shown when an assertion occurs during node measurement [\#1022](https://github.com/TextureGroup/Texture/pull/1022) ([nguyenhuy](https://github.com/nguyenhuy)) +- Add an introduction for ASCornerLayoutSpec in layout2-layoutspec-types.md \#trivial [\#1021](https://github.com/TextureGroup/Texture/pull/1021) ([huang-kun](https://github.com/huang-kun)) +- Add showsHorizontal\(Vertical\)ScrollIndicator property applying from pending state \#trivial [\#1016](https://github.com/TextureGroup/Texture/pull/1016) ([maicki](https://github.com/maicki)) +- \[IGListKit\] Adds missing UIScrollViewDelegate method to DataSource proxy [\#1015](https://github.com/TextureGroup/Texture/pull/1015) ([wannabehero](https://github.com/wannabehero)) +- Introduce let / var macros and some further cleanup [\#1012](https://github.com/TextureGroup/Texture/pull/1012) ([maicki](https://github.com/maicki)) +- Properly consider node for responder methods [\#1008](https://github.com/TextureGroup/Texture/pull/1008) ([maicki](https://github.com/maicki)) +- Background image load api [\#1007](https://github.com/TextureGroup/Texture/pull/1007) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Add move detection and support to ASLayoutTransition [\#1006](https://github.com/TextureGroup/Texture/pull/1006) ([wiseoldduck](https://github.com/wiseoldduck)) +- Fix warnings and a memory leak \#trivial [\#1003](https://github.com/TextureGroup/Texture/pull/1003) ([maicki](https://github.com/maicki)) +- Rewrite Swift Example [\#1002](https://github.com/TextureGroup/Texture/pull/1002) ([maicki](https://github.com/maicki)) +- Remove yoga layout spec, which has been superseded [\#999](https://github.com/TextureGroup/Texture/pull/999) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Optimize drawing code + add examples how to round corners [\#996](https://github.com/TextureGroup/Texture/pull/996) ([maicki](https://github.com/maicki)) +- Fix typo in containers-asviewcontroller.md [\#989](https://github.com/TextureGroup/Texture/pull/989) ([muukii](https://github.com/muukii)) +- Create transfer-array method and use it [\#987](https://github.com/TextureGroup/Texture/pull/987) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add missing instance variables in ASTextNode and warnings cleanup \#trivial [\#984](https://github.com/TextureGroup/Texture/pull/984) ([maicki](https://github.com/maicki)) +- Optimize layout flattening [\#982](https://github.com/TextureGroup/Texture/pull/982) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Changed lost images to existing one. \#trivial [\#981](https://github.com/TextureGroup/Texture/pull/981) ([tataevr](https://github.com/tataevr)) +- \[texturegroup.org\] Use valid link for Upgrade to 2.0 beta 1 page \#trivial [\#980](https://github.com/TextureGroup/Texture/pull/980) ([mikezucc](https://github.com/mikezucc)) +- Adds support for having multiple interface state delegates. [\#979](https://github.com/TextureGroup/Texture/pull/979) ([garrettmoon](https://github.com/garrettmoon)) +- Create an experiment to remove extra collection teardown step [\#975](https://github.com/TextureGroup/Texture/pull/975) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove unused/unneeded header macros [\#973](https://github.com/TextureGroup/Texture/pull/973) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Standardize "extern" decls on AS\_EXTERN [\#972](https://github.com/TextureGroup/Texture/pull/972) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- ASConfiguration version check only when have json dict [\#971](https://github.com/TextureGroup/Texture/pull/971) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Pointer check [\#970](https://github.com/TextureGroup/Texture/pull/970) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Reduce usage of autorelease pools [\#968](https://github.com/TextureGroup/Texture/pull/968) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Update showcase to include Apollo for Reddit [\#967](https://github.com/TextureGroup/Texture/pull/967) ([christianselig](https://github.com/christianselig)) +- Fix crash when call needsMainThreadDeallocation on NSProxy instances \#trivial [\#965](https://github.com/TextureGroup/Texture/pull/965) ([nguyenhuy](https://github.com/nguyenhuy)) +- Fix name typo \#trivial [\#963](https://github.com/TextureGroup/Texture/pull/963) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Generalize the main thread ivar deallocation system [\#959](https://github.com/TextureGroup/Texture/pull/959) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add support for acquiring multiple locks at once [\#958](https://github.com/TextureGroup/Texture/pull/958) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Clean up async transaction system a bit [\#955](https://github.com/TextureGroup/Texture/pull/955) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Added 'Waplog' to showcase. [\#953](https://github.com/TextureGroup/Texture/pull/953) ([malikkuru](https://github.com/malikkuru)) +- Make ASPerformMainThreadDeallocation visible in C [\#952](https://github.com/TextureGroup/Texture/pull/952) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Cut 2.7 release [\#949](https://github.com/TextureGroup/Texture/pull/949) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fixed removing node from supernode after layout transition [\#937](https://github.com/TextureGroup/Texture/pull/937) ([atitovdev](https://github.com/atitovdev)) +- add ASTextNode2 snapshot test [\#935](https://github.com/TextureGroup/Texture/pull/935) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- \[ASTextNode\] One more check variables before calling delegate method \#trivial [\#922](https://github.com/TextureGroup/Texture/pull/922) ([Flatout73](https://github.com/Flatout73)) +- Assert node did load before did enter visible way 1 [\#886](https://github.com/TextureGroup/Texture/pull/886) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Renew supplementary node on relayout [\#842](https://github.com/TextureGroup/Texture/pull/842) ([wsdwsd0829](https://github.com/wsdwsd0829)) -## 2.5 +## [2.7](https://github.com/TextureGroup/Texture/tree/2.7) (2018-05-29) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.6...2.7) -- [ASCollectionNode] Add -isProcessingUpdates and -onDidFinishProcessingUpdates: APIs. [#522](https://github.com/TextureGroup/Texture/pull/522) [Scott Goodson](https://github.com/appleguy) -- [Accessibility] Add .isAccessibilityContainer property, allowing automatic aggregation of children's a11y labels. [#468][Scott Goodson](https://github.com/appleguy) -- [ASImageNode] Enabled .clipsToBounds by default, fixing the use of .cornerRadius and clipping of GIFs. [Scott Goodson](https://github.com/appleguy) [#466](https://github.com/TextureGroup/Texture/pull/466) -- Fix an issue in layout transition that causes it to unexpectedly use the old layout [Huy Nguyen](https://github.com/nguyenhuy) [#464](https://github.com/TextureGroup/Texture/pull/464) -- Add -[ASDisplayNode detailedLayoutDescription] property to aid debugging. [Adlai Holler](https://github.com/Adlai-Holler) [#476](https://github.com/TextureGroup/Texture/pull/476) -- Fix an issue that causes calculatedLayoutDidChange being called needlessly. [Huy Nguyen](https://github.com/nguyenhuy) [#490](https://github.com/TextureGroup/Texture/pull/490) -- Negate iOS 11 automatic estimated table row heights. [Christian Selig](https://github.com/christianselig) [#485](https://github.com/TextureGroup/Texture/pull/485) -- Add content inset and offset bridging properties to ASTableNode and ASCollectionNode. Deprecate related properties and methods in ASTableView and ASCollectionView [Huy Nguyen](https://github.com/nguyenhuy) [#460](https://github.com/TextureGroup/Texture/pull/460) [#560](https://github.com/TextureGroup/Texture/pull/560) -- Remove re-entrant access to self.view when applying initial pending state. [Adlai Holler](https://github.com/Adlai-Holler) [#510](https://github.com/TextureGroup/Texture/pull/510) -- Small improvements in ASCollectionLayout [Huy Nguyen](https://github.com/nguyenhuy) [#509](https://github.com/TextureGroup/Texture/pull/509) [#513](https://github.com/TextureGroup/Texture/pull/513) [#562]((https://github.com/TextureGroup/Texture/pull/562) -- Fix retain cycle between ASImageNode and PINAnimatedImage [Phil Larson](https://github.com/plarson) [#520](https://github.com/TextureGroup/Texture/pull/520) -- Change the API for disabling logging from a compiler flag to a runtime C function ASDisableLogging(). [Adlai Holler](https://github.com/Adlai-Holler) [#528](https://github.com/TextureGroup/Texture/pull/528) -- Table and collection views to consider content inset when calculating (default) element size range [Huy Nguyen](https://github.com/nguyenhuy) [#525](https://github.com/TextureGroup/Texture/pull/525) -- [ASEditableTextNode] added -editableTextNodeShouldBeginEditing to ASEditableTextNodeDelegate to mirror the corresponding method from UITextViewDelegate. [Yan S.](https://github.com/yans) [#535](https://github.com/TextureGroup/Texture/pull/535) -- [Breaking] Remove APIs that have been deprecated since 2.0 and/or for at least 6 months [Huy Nguyen](https://github.com/nguyenhuy) [#529](https://github.com/TextureGroup/Texture/pull/529) -- [ASDisplayNode] Ensure `-displayWillStartAsynchronously:` and `-displayDidFinish` are invoked on rasterized subnodes. [Eric Scheers](https://github.com/smeis) [#532](https://github.com/TextureGroup/Texture/pull/532) -- Fixed a memory corruption issue in the ASImageNode display system. [Adlai Holler](https://github.com/Adlai-Holler) [#555](https://github.com/TextureGroup/Texture/pull/555) -- [Breaking] Rename ASCollectionGalleryLayoutSizeProviding to ASCollectionGalleryLayoutPropertiesProviding. Besides a fixed item size, it now can provide interitem and line spacings, as well as section inset [Huy Nguyen](https://github.com/nguyenhuy) [#496](https://github.com/TextureGroup/Texture/pull/496) [#533](https://github.com/TextureGroup/Texture/pull/533) -- Deprecate `-[ASDisplayNode displayWillStart]` in favor of `-displayWillStartAsynchronously:` [Huy Nguyen](https://github.com/nguyenhuy) [#536](https:/ -/github.com/TextureGroup/Texture/pull/536) -- Add support for URLs on ASNetworkImageNode. [Garrett Moon](https://github.com/garrettmoon) -- [ASImageNode] Always dealloc images in a background queue [Huy Nguyen](https://github.com/nguyenhuy) [#561](https://github.com/TextureGroup/Texture/pull/561) -- Mark ASRunLoopQueue as drained if it contains only NULLs [Cesar Estebanez](https://github.com/cesteban) [#558](https://github.com/TextureGroup/Texture/pull/558) -- Fix crashes caused by failing to unlock or destroy a static mutex while the app is being terminated [Huy Nguyen](https://github.com/nguyenhuy) +**Merged pull requests:** -## 2.4 -- Fix an issue where inserting/deleting sections could lead to inconsistent supplementary element behavior. [Adlai Holler](https://github.com/Adlai-Holler) -- Overhaul logging and add activity tracing support. [Adlai Holler](https://github.com/Adlai-Holler) -- Fix a crash where scrolling a table view after entering editing mode could lead to bad internal states in the table. [Huy Nguyen](https://github.com/nguyenhuy) [#416](https://github.com/TextureGroup/Texture/pull/416/) -- Fix a crash in collection view that occurs if batch updates are performed while scrolling [Huy Nguyen](https://github.com/nguyenhuy) [#378](https://github.com/TextureGroup/Texture/issues/378) -- Some improvements in ASCollectionView [Huy Nguyen](https://github.com/nguyenhuy) [#407](https://github.com/TextureGroup/Texture/pull/407) -- Small refactors in ASDataController [Huy Nguyen](https://github.com/TextureGroup/Texture/pull/443) [#443](https://github.com/TextureGroup/Texture/pull/443) -- [ASCollectionView] Add delegate bridging and index space translation for missing UICollectionViewLayout properties. [Scott Goodson](https://github.com/appleguy) -- [ASTextNode2] Add initial implementation for link handling. [Scott Goodson](https://github.com/appleguy) [#396](https://github.com/TextureGroup/Texture/pull/396) -- [ASTextNode2] Provide compile flag to globally enable new implementation of ASTextNode: ASTEXTNODE_EXPERIMENT_GLOBAL_ENABLE. [Scott Goodson](https://github.com/appleguy) [#396](https://github.com/TextureGroup/Texture/pull/410) -- Add ASCollectionGalleryLayoutDelegate - an async collection layout that makes same-size collections (e.g photo galleries, pagers, etc) fast and lightweight! [Huy Nguyen](https://github.com/nguyenhuy/) [#76](https://github.com/TextureGroup/Texture/pull/76) [#451](https://github.com/TextureGroup/Texture/pull/451) -- Fix an issue that causes infinite layout loop in ASDisplayNode after [#428](https://github.com/TextureGroup/Texture/pull/428) [Huy Nguyen](https://github.com/nguyenhuy) [#455](https://github.com/TextureGroup/Texture/pull/455) -- Rename ASCellNode.viewModel to ASCellNode.nodeModel to reduce collisions with subclass properties implemented by clients. [Adlai Holler](https://github.com/Adlai-Holler) [#504](https://github.com/TextureGroup/Texture/pull/504) +- Update AppIcon in showcase [\#946](https://github.com/TextureGroup/Texture/pull/946) ([muukii](https://github.com/muukii)) +- Update tip-1-nodeBlocks.md [\#943](https://github.com/TextureGroup/Texture/pull/943) ([sagarbhosale](https://github.com/sagarbhosale)) +- \[ASTableView\] Generate a new cell layout if existing ones are invalid [\#942](https://github.com/TextureGroup/Texture/pull/942) ([nguyenhuy](https://github.com/nguyenhuy)) +- Update to unsplash [\#938](https://github.com/TextureGroup/Texture/pull/938) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASTextNode2\] Simplify compare-assign check & lock \_pointScaleFactors accessor \#trivial [\#934](https://github.com/TextureGroup/Texture/pull/934) ([appleguy](https://github.com/appleguy)) +- Create a new dealloc queue that is more efficient [\#931](https://github.com/TextureGroup/Texture/pull/931) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASImageNode+AnimatedImage\] Fix early return when animatedImage is nil in setAnimatedImage \#trivial [\#925](https://github.com/TextureGroup/Texture/pull/925) ([flovouin](https://github.com/flovouin)) +- Remove assert. fix \#878 \#914 [\#924](https://github.com/TextureGroup/Texture/pull/924) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Always call out to delegate for experiments, whether enabled or not [\#923](https://github.com/TextureGroup/Texture/pull/923) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASTextNode2\] Upgrade lock safety by protecting all ivars \(including rarely-changed ones\). [\#918](https://github.com/TextureGroup/Texture/pull/918) ([appleguy](https://github.com/appleguy)) +- \[ASCollectionNode/ASTableNode\] Fix a crash occurs while remeasuring cell nodes [\#917](https://github.com/TextureGroup/Texture/pull/917) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASDisplayNode\] Improve thread-safety of didExitHierarchy \#trivial [\#916](https://github.com/TextureGroup/Texture/pull/916) ([nguyenhuy](https://github.com/nguyenhuy)) +- Prevent UITextView from updating contentOffset while deallocating [\#915](https://github.com/TextureGroup/Texture/pull/915) ([maicki](https://github.com/maicki)) +- Fix ASDKgram-Swift to avoid 'error parsing JSON within PhotoModel Init' [\#913](https://github.com/TextureGroup/Texture/pull/913) ([kenstir](https://github.com/kenstir)) +- \#trivial Add forgotten experiment into Schemas/configuration.json [\#912](https://github.com/TextureGroup/Texture/pull/912) ([garrettmoon](https://github.com/garrettmoon)) +- \#trivial Fix the C++ assertion [\#911](https://github.com/TextureGroup/Texture/pull/911) ([garrettmoon](https://github.com/garrettmoon)) +- Add 'iDiva - Beauty & Wedding tips' to Showcase [\#909](https://github.com/TextureGroup/Texture/pull/909) ([sudhanshutil](https://github.com/sudhanshutil)) +- Issue ASNetworkImageNode callbacks off main thread [\#908](https://github.com/TextureGroup/Texture/pull/908) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASTextNode\] Fix a deadlock that could occur when enabling experimental ASTextNode2 via ASConfiguration [\#903](https://github.com/TextureGroup/Texture/pull/903) ([appleguy](https://github.com/appleguy)) +- \[Docs\] Add new lightning talk from Buffer \#trivial [\#902](https://github.com/TextureGroup/Texture/pull/902) ([ay8s](https://github.com/ay8s)) +- Request std=c++11 dialect again, and add warning [\#900](https://github.com/TextureGroup/Texture/pull/900) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASTextNode\] Check variables before calling delegate method \#trivial [\#898](https://github.com/TextureGroup/Texture/pull/898) ([Jauzee](https://github.com/Jauzee)) +- ASDKFastImageNamed UIImage initializer nullability \#trivial [\#897](https://github.com/TextureGroup/Texture/pull/897) ([alexhillc](https://github.com/alexhillc)) +- \#trivial Fixes an issue where playback may not start [\#896](https://github.com/TextureGroup/Texture/pull/896) ([garrettmoon](https://github.com/garrettmoon)) +- Update configuration schema \#trivial [\#893](https://github.com/TextureGroup/Texture/pull/893) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- replace ` with code in containers-overview.md [\#884](https://github.com/TextureGroup/Texture/pull/884) ([everettjf](https://github.com/everettjf)) +- \[Docs\] Fix typos in layout specs section \#trivial [\#883](https://github.com/TextureGroup/Texture/pull/883) ([morozkin](https://github.com/morozkin)) +- Match interfacestate update sequence to uikit [\#882](https://github.com/TextureGroup/Texture/pull/882) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Add experiment to skip creating UIViews altogether for constants [\#881](https://github.com/TextureGroup/Texture/pull/881) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix ASDISPLAYNODE\_ASSERTIONS\_ENABLED and ASDefaultPlaybackButton warnings \#trivial [\#880](https://github.com/TextureGroup/Texture/pull/880) ([maicki](https://github.com/maicki)) +- Fix macro definition for AS\_KDEBUG\_ENABLE producing warning \#trivial [\#879](https://github.com/TextureGroup/Texture/pull/879) ([andrewrohn](https://github.com/andrewrohn)) +- Fix pager node for interface coalescing [\#877](https://github.com/TextureGroup/Texture/pull/877) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Standardize Property Declaration Style in Core Classes [\#870](https://github.com/TextureGroup/Texture/pull/870) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[NoCopyRendering\] In non-VM case, use calloc to get a zerod buffer \#trivial [\#869](https://github.com/TextureGroup/Texture/pull/869) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Check in Xcode 9.3 "workspace checks" file [\#868](https://github.com/TextureGroup/Texture/pull/868) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove Redundant Atomic Store from Recursive Unfair Lock in Recursive Case \#trivial [\#867](https://github.com/TextureGroup/Texture/pull/867) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Update Podspec [\#866](https://github.com/TextureGroup/Texture/pull/866) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[Issue 838\] Update ASCeilPixelValue and ASRoundPixelValue [\#864](https://github.com/TextureGroup/Texture/pull/864) ([rcancro](https://github.com/rcancro)) +- Disable interface coalescing [\#862](https://github.com/TextureGroup/Texture/pull/862) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Introduce ASRecursiveUnfairLock and tests [\#858](https://github.com/TextureGroup/Texture/pull/858) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Make NSIndexSet+ASHelpers.h reference local \#trivial [\#857](https://github.com/TextureGroup/Texture/pull/857) ([dmaclach](https://github.com/dmaclach)) +- Make ASBatchContext lock-free \#trivial [\#854](https://github.com/TextureGroup/Texture/pull/854) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASNetworkImageNode\] Replace NSUUID sentinel with integer \#trivial [\#852](https://github.com/TextureGroup/Texture/pull/852) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Make objects conform to NSLocking [\#851](https://github.com/TextureGroup/Texture/pull/851) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Make cache support animated image [\#850](https://github.com/TextureGroup/Texture/pull/850) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- \[bugfix\] Align timing of interface coalescing and range update. \#trivial [\#847](https://github.com/TextureGroup/Texture/pull/847) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Update layout2-layout-element-properties.md [\#844](https://github.com/TextureGroup/Texture/pull/844) ([arielelkin](https://github.com/arielelkin)) +- Use NS\_RETURNS\_RETAINED macro to save time [\#843](https://github.com/TextureGroup/Texture/pull/843) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Handle nil backgroundColor in ASTextNode2 \#trivial [\#841](https://github.com/TextureGroup/Texture/pull/841) ([maicki](https://github.com/maicki)) +- Put back VM flag in ASCGImageBuffer [\#839](https://github.com/TextureGroup/Texture/pull/839) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Order items in XCode project navigator by name [\#835](https://github.com/TextureGroup/Texture/pull/835) ([OleksiyA](https://github.com/OleksiyA)) +- \[NoCopyRendering\] Use vm instead of malloc [\#833](https://github.com/TextureGroup/Texture/pull/833) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASTextNode2\] Fix background color drawing [\#831](https://github.com/TextureGroup/Texture/pull/831) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix Text Node Thread Sanitizer Warning [\#830](https://github.com/TextureGroup/Texture/pull/830) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- access view first before checking canBecome/Resign responder in becomeResponder methods [\#829](https://github.com/TextureGroup/Texture/pull/829) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- \[\#trivial\] fixes rendered image quality on networked image nodes whic… [\#826](https://github.com/TextureGroup/Texture/pull/826) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASTextNode\] Fix locking, add test for issue \#trivial [\#825](https://github.com/TextureGroup/Texture/pull/825) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[\#trivial\] I don't think we need this extra locked method. [\#824](https://github.com/TextureGroup/Texture/pull/824) ([garrettmoon](https://github.com/garrettmoon)) +- \#trivial Hopefully made this a bit more readable. [\#823](https://github.com/TextureGroup/Texture/pull/823) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASTextNode\] Avoid acquiring instance lock multiple times \#trivial [\#820](https://github.com/TextureGroup/Texture/pull/820) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[Showcase\] Fix mensXP showcase and attach Vingle-Tech-Talk Medium [\#818](https://github.com/TextureGroup/Texture/pull/818) ([GeekTree0101](https://github.com/GeekTree0101)) +- \[ASDisplayNode\] Add unit tests for layout z-order changes \(with an open issue to fix\). [\#816](https://github.com/TextureGroup/Texture/pull/816) ([appleguy](https://github.com/appleguy)) +- \[ASDKGram Example\] image\_url has been changed from URL string to Array by 5… [\#813](https://github.com/TextureGroup/Texture/pull/813) ([kaar3k](https://github.com/kaar3k)) +- Replace pthread specifics with C11 thread-local variables [\#811](https://github.com/TextureGroup/Texture/pull/811) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Upgrade dangerfile [\#810](https://github.com/TextureGroup/Texture/pull/810) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASDisplayNode\] Fix an issue that causes a node to sometimes return an outdated calculated size or size range [\#808](https://github.com/TextureGroup/Texture/pull/808) ([nguyenhuy](https://github.com/nguyenhuy)) +- Avoid triggering main thread assertions in collection/table dealloc \#trivial [\#803](https://github.com/TextureGroup/Texture/pull/803) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Update IGListKit dependency to allow for updated versions [\#802](https://github.com/TextureGroup/Texture/pull/802) ([johntmcintosh](https://github.com/johntmcintosh)) +- \[ASDisplayNode\] Consolidate main thread initialization and allow apps to invoke it manually instead of +load. [\#798](https://github.com/TextureGroup/Texture/pull/798) ([appleguy](https://github.com/appleguy)) +- \[ASWrapperCellNode\] Introduce a new class allowing more control of UIKit passthrough cells. [\#797](https://github.com/TextureGroup/Texture/pull/797) ([appleguy](https://github.com/appleguy)) +- Add missing scrollViewWillEndDragging passthrough delegate [\#796](https://github.com/TextureGroup/Texture/pull/796) ([xezero](https://github.com/xezero)) +- Fix ASTextNode2 is accessing backgroundColor off main while sizing / layout is happening [\#794](https://github.com/TextureGroup/Texture/pull/794) ([maicki](https://github.com/maicki)) +- \[ASTableNode & ASCollectionNode\] Keepalive reference for node if their view is necessarily alive \(has a superview\). [\#793](https://github.com/TextureGroup/Texture/pull/793) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- \[ASDisplayNode layout\] Fix an issue that sometimes causes a node's pending layout to not be applied [\#792](https://github.com/TextureGroup/Texture/pull/792) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASRangeController\] Fix stability of "minimum" rangeMode if the app has more than one layout before scrolling. [\#790](https://github.com/TextureGroup/Texture/pull/790) ([appleguy](https://github.com/appleguy)) +- Fix UIResponder handling with view backing ASDisplayNode [\#789](https://github.com/TextureGroup/Texture/pull/789) ([maicki](https://github.com/maicki)) +- New runloop queue to coalesce Interface state update calls. [\#788](https://github.com/TextureGroup/Texture/pull/788) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- \[Graphics contexts\] Retain the reference color space \#trivial [\#784](https://github.com/TextureGroup/Texture/pull/784) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Get CatDealsCollectionView example running again \#trivial [\#783](https://github.com/TextureGroup/Texture/pull/783) ([maicki](https://github.com/maicki)) +- Improve nullable annotations for \_ASDisplayLayer and \_ASDisplayView \#trivial [\#780](https://github.com/TextureGroup/Texture/pull/780) ([maicki](https://github.com/maicki)) +- \[ASDisplayNode\] Force a layout pass on a visible node as soon as it enters preload state [\#779](https://github.com/TextureGroup/Texture/pull/779) ([nguyenhuy](https://github.com/nguyenhuy)) +- Improve ASNetworkImageNode delegate callout behavior [\#778](https://github.com/TextureGroup/Texture/pull/778) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix capturing self in the block while loading image in ASNetworkImageNode [\#777](https://github.com/TextureGroup/Texture/pull/777) ([morozkin](https://github.com/morozkin)) +- Fix synchronous state of node if +viewClass or +layerClass is overwritten \#trivial [\#776](https://github.com/TextureGroup/Texture/pull/776) ([maicki](https://github.com/maicki)) +- Add support for providing additional info to network image node delegate [\#775](https://github.com/TextureGroup/Texture/pull/775) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Expose asyncdisplaykit\_node in \_ASDisplayView same as in \_ASDisplayLayer \#trivial [\#773](https://github.com/TextureGroup/Texture/pull/773) ([maicki](https://github.com/maicki)) +- Improve no-copy rendering experiment, remove +load method [\#771](https://github.com/TextureGroup/Texture/pull/771) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix typos in layout2-layoutspec-types.md \#trivial [\#770](https://github.com/TextureGroup/Texture/pull/770) ([morozkin](https://github.com/morozkin)) +- Update PINCache [\#769](https://github.com/TextureGroup/Texture/pull/769) ([justinswart](https://github.com/justinswart)) +- Fix misprint \#trivial [\#768](https://github.com/TextureGroup/Texture/pull/768) ([Flatout73](https://github.com/Flatout73)) +- NoCopyRendering experiment: Fix possible memory leak if image node rendering is canceled \#trivial [\#765](https://github.com/TextureGroup/Texture/pull/765) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Node tint color [\#764](https://github.com/TextureGroup/Texture/pull/764) ([ShogunPhyched](https://github.com/ShogunPhyched)) +- Revert "Faster collection operations" [\#759](https://github.com/TextureGroup/Texture/pull/759) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASPrimitiveTraitCollection\] Always treat preferredContentSize as a potential nil \#trivial [\#757](https://github.com/TextureGroup/Texture/pull/757) ([ypogribnyi](https://github.com/ypogribnyi)) +- Update subclassing.md [\#753](https://github.com/TextureGroup/Texture/pull/753) ([janechoi6](https://github.com/janechoi6)) +- \[ASDisplayNode\] Don't force a layout pass on a visible node that enters preload state [\#751](https://github.com/TextureGroup/Texture/pull/751) ([nguyenhuy](https://github.com/nguyenhuy)) +- Fix the dangerfile [\#750](https://github.com/TextureGroup/Texture/pull/750) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASDisplayNode\] Always return the thread-safe cornerRadius property, even in slow CALayer rounding mode [\#749](https://github.com/TextureGroup/Texture/pull/749) ([nguyenhuy](https://github.com/nguyenhuy)) +- Faster collection operations [\#748](https://github.com/TextureGroup/Texture/pull/748) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Create a centralized configuration API [\#747](https://github.com/TextureGroup/Texture/pull/747) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Update dangerfile for 2018 \#trivial [\#746](https://github.com/TextureGroup/Texture/pull/746) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Raise deployment target to iOS 9 [\#743](https://github.com/TextureGroup/Texture/pull/743) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add an experimental "no-copy" renderer [\#741](https://github.com/TextureGroup/Texture/pull/741) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fixed: completeBatchFetching is called on a background thread [\#731](https://github.com/TextureGroup/Texture/pull/731) ([aaronr93](https://github.com/aaronr93)) +- \[tvOS\] Fixes errors when building against tvOS SDK [\#728](https://github.com/TextureGroup/Texture/pull/728) ([alexhillc](https://github.com/alexhillc)) +- \[ASCellNode\] focusStyle mapping [\#727](https://github.com/TextureGroup/Texture/pull/727) ([alexhillc](https://github.com/alexhillc)) +- \[ASDisplayNode\] Provide safeAreaInsets and layoutMargins bridge [\#685](https://github.com/TextureGroup/Texture/pull/685) ([ypogribnyi](https://github.com/ypogribnyi)) +- \[ASTraitCollection\] Add missing properties to ASTraitCollection [\#625](https://github.com/TextureGroup/Texture/pull/625) ([ypogribnyi](https://github.com/ypogribnyi)) -## 2.3.4 -- [Yoga] Rewrite YOGA_TREE_CONTIGUOUS mode with improved behavior and cleaner integration [Scott Goodson](https://github.com/appleguy) -- [ASTraitCollection] Convert ASPrimitiveTraitCollection from lock to atomic. [Scott Goodson](https://github.com/appleguy) -- Add a synchronous mode to ASCollectionNode, for colletion view data source debugging. [Hannah Troisi](https://github.com/hannahmbanana) -- [ASDisplayNode+Layout] Add check for orphaned nodes after layout transition to clean up. #336. [Scott Goodson](https://github.com/appleguy) -- Fixed an issue where GIFs with placeholders never had their placeholders uncover the GIF. [Garrett Moon](https://github.com/garrettmoon) -- [Yoga] Implement ASYogaLayoutSpec, a simplified integration strategy for Yoga-powered layout calculation. [Scott Goodson](https://github.com/appleguy) -- Fixed an issue where calls to setNeedsDisplay and setNeedsLayout would stop working on loaded nodes. [Garrett Moon](https://github.com/garrettmoon) -- Migrated unit tests to OCMock 3.4 (from 2.2) and improved the multiplex image node tests. [Adlai Holler](https://github.com/Adlai-Holler) -- Fix CollectionNode double-load issue. This should significantly improve performance in cases where a collection node has content immediately available on first layout i.e. not fetched from the network. [Adlai Holler](https://github.com/Adlai-Holler) -- Overhaul layout flattening algorithm [Huy Nguyen](https://github.com/nguyenhuy) [#395](https://github.com/TextureGroup/Texture/pull/395). +## [2.6](https://github.com/TextureGroup/Texture/tree/2.6) (2018-01-12) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.5.1...2.6) -## 2.3.3 -- [ASTextKitFontSizeAdjuster] Replace use of NSAttributedString's boundingRectWithSize:options:context: with NSLayoutManager's boundingRectForGlyphRange:inTextContainer: [Ricky Cancro](https://github.com/rcancro) -- Add support for IGListKit post-removal-of-IGListSectionType, in preparation for IGListKit 3.0.0 release. [Adlai Holler](https://github.com/Adlai-Holler) [#49](https://github.com/TextureGroup/Texture/pull/49) -- Fix `__has_include` check in ASLog.h [Philipp Smorygo](Philipp.Smorygo@jetbrains.com) -- Fix potential deadlock in ASControlNode [Garrett Moon](https://github.com/garrettmoon) -- [Yoga Beta] Improvements to the experimental support for Yoga layout [Scott Goodson](appleguy) -- Make cell node `indexPath` and `supplementaryElementKind` atomic so you can read from any thread. [Adlai-Holler](https://github.com/Adlai-Holler) [#49](https://github.com/TextureGroup/Texture/pull/74) -- Update the rasterization API and un-deprecate it. [Adlai Holler](https://github.com/Adlai-Holler)[#82](https://github.com/TextureGroup/Texture/pull/49) -- Simplified & optimized hashing code. [Adlai Holler](https://github.com/Adlai-Holler) [#86](https://github.com/TextureGroup/Texture/pull/86) -- Improve the performance & safety of ASDisplayNode subnodes. [Adlai Holler](https://github.com/Adlai-Holler) [#223](https://github.com/TextureGroup/Texture/pull/223) -- Move more properties from ASTableView, ASCollectionView to their respective node classes. [Adlai Holler](https://github.com/Adlai-Holler) -- Remove finalLayoutElement [Michael Schneider](https://github.com/maicki)[#96](https://github.com/TextureGroup/Texture/pull/96) -- Add ASPageTable - A map table for fast retrieval of objects within a certain page [Huy Nguyen](https://github.com/nguyenhuy) -- Add new public `-supernodes`, `-supernodesIncludingSelf`, and `-supernodeOfClass:includingSelf:` methods. [Adlai Holler](https://github.com/Adlai-Holler)[#246](https://github.com/TextureGroup/Texture/pull/246) -- Improve our handling supernode traversal to avoid loading layers and fix assertion failures you might hit in debug. [Adlai Holler](https://github.com/Adlai-Holler)[#246](https://github.com/TextureGroup/Texture/pull/246) -- [ASDisplayNode] Pass drawParameter in rendering context callbacks [Michael Schneider](https://github.com/maicki)[#248](https://github.com/TextureGroup/Texture/pull/248) -- [ASTextNode] Move to class method of drawRect:withParameters:isCancelled:isRasterizing: for drawing [Michael Schneider](https://github.com/maicki)[#232](https://github.com/TextureGroup/Texture/pull/232) -- [ASDisplayNode] Remove instance:-drawRect:withParameters:isCancelled:isRasterizing: (https://github.com/maicki)[#232](https://github.com/TextureGroup/Texture/pull/232) -- [ASTextNode] Add an experimental new implementation. See `+[ASTextNode setExperimentOptions:]`. [Adlai Holler](https://github.com/Adlai-Holler)[#259](https://github.com/TextureGroup/Texture/pull/259) -- [ASVideoNode] Added error reporing to ASVideoNode and it's delegate [#260](https://github.com/TextureGroup/Texture/pull/260) -- [ASCollectionNode] Fixed conversion of item index paths between node & view. [Adlai Holler](https://github.com/Adlai-Holler) [#262](https://github.com/TextureGroup/Texture/pull/262) -- [Layout] Extract layout implementation code into it's own subcategories [Michael Schneider](https://github.com/maicki)[#272](https://github.com/TextureGroup/Texture/pull/272) -- [Fix] Fix a potential crash when cell nodes that need layout are deleted during the same runloop. [Adlai Holler](https://github.com/Adlai-Holler) [#279](https://github.com/TextureGroup/Texture/pull/279) -- [Batch fetching] Add ASBatchFetchingDelegate that takes scroll velocity and remaining time into account [Huy Nguyen](https://github.com/nguyenhuy) [#281](https://github.com/TextureGroup/Texture/pull/281) -- [Fix] Fix a major regression in our image node contents caching. [Adlai Holler](https://github.com/Adlai-Holler) [#287](https://github.com/TextureGroup/Texture/pull/287) -- [Fix] Fixed a bug where ASVideoNodeDelegate error reporting callback would crash an app because of not responding to selector. [Sergey Petrachkov](https://github.com/Petrachkov) [#291](https://github.com/TextureGroup/Texture/issues/291) -- [IGListKit] Add IGListKit headers to public section of Xcode project [Michael Schneider](https://github.com/maicki)[#286](https://github.com/TextureGroup/Texture/pull/286) -- [Layout] Ensure -layout and -layoutDidFinish are called only if a node is loaded. [Huy Nguyen](https://github.com/nguyenhuy) [#285](https://github.com/TextureGroup/Texture/pull/285) -- [Layout Debugger] Small changes needed for the coming layout debugger [Huy Nguyen](https://github.com/nguyenhuy) [#337](https://github.com/TextureGroup/Texture/pull/337) +**Merged pull requests:** + +- Add MensXP to Showcase [\#739](https://github.com/TextureGroup/Texture/pull/739) ([sudhanshutil](https://github.com/sudhanshutil)) +- Enable collection node interactive moves [\#735](https://github.com/TextureGroup/Texture/pull/735) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add Blendle to our showcase page [\#721](https://github.com/TextureGroup/Texture/pull/721) ([nguyenhuy](https://github.com/nguyenhuy)) +- \#trivial Fixes image nodes being stuck not being able to download image [\#720](https://github.com/TextureGroup/Texture/pull/720) ([garrettmoon](https://github.com/garrettmoon)) +- Reimplement ASRectTable using unordered\_map to avoid obscure NSMapTable exception. [\#719](https://github.com/TextureGroup/Texture/pull/719) ([appleguy](https://github.com/appleguy)) +- Add missing flags for ASCollectionDelegate [\#718](https://github.com/TextureGroup/Texture/pull/718) ([ilyailya](https://github.com/ilyailya)) +- Add support for toggling logs off and back on at runtime [\#714](https://github.com/TextureGroup/Texture/pull/714) ([johntmcintosh](https://github.com/johntmcintosh)) +- \[Update Showcase\] Update Showcase, add Vingle very community [\#711](https://github.com/TextureGroup/Texture/pull/711) ([GeekTree0101](https://github.com/GeekTree0101)) +- \[ASCollectionElement\] Check for nil elements on ASTableView as well. [\#710](https://github.com/TextureGroup/Texture/pull/710) ([cesteban](https://github.com/cesteban)) +- Ensure an ASM enabled node applies its pending layout when enters preload state [\#706](https://github.com/TextureGroup/Texture/pull/706) ([nguyenhuy](https://github.com/nguyenhuy)) +- The ASDKgram example doesn't compile. [\#700](https://github.com/TextureGroup/Texture/pull/700) ([onato](https://github.com/onato)) +- Revert Adds support for specifying a quality indexed array of URLs [\#699](https://github.com/TextureGroup/Texture/pull/699) ([garrettmoon](https://github.com/garrettmoon)) +- Correct Synchronous Concurrency Talk Link [\#698](https://github.com/TextureGroup/Texture/pull/698) ([ay8s](https://github.com/ay8s)) +- \[ASDisplayNode+Layout\] Ensure a pending layout is applied once [\#695](https://github.com/TextureGroup/Texture/pull/695) ([nguyenhuy](https://github.com/nguyenhuy)) +- Add missing \ tags in Layout API Sizing docs [\#691](https://github.com/TextureGroup/Texture/pull/691) ([richardhenry](https://github.com/richardhenry)) +- Fix bug that breaks ASNodeController docs page [\#690](https://github.com/TextureGroup/Texture/pull/690) ([richardhenry](https://github.com/richardhenry)) +- Add a recent talk by @smeis at CocoaHeadsNL [\#687](https://github.com/TextureGroup/Texture/pull/687) ([nguyenhuy](https://github.com/nguyenhuy)) +- Update subtree-rasterization.md [\#679](https://github.com/TextureGroup/Texture/pull/679) ([WymzeeLabs](https://github.com/WymzeeLabs)) +- Update layer-backing.md [\#678](https://github.com/TextureGroup/Texture/pull/678) ([WymzeeLabs](https://github.com/WymzeeLabs)) +- \[iOS11\] Update project settings and fix errors [\#676](https://github.com/TextureGroup/Texture/pull/676) ([Eke](https://github.com/Eke)) +- Fix swift sample. [\#669](https://github.com/TextureGroup/Texture/pull/669) ([rwinzhang](https://github.com/rwinzhang)) +- Bugfix/fix yoga logging aligning api changes [\#668](https://github.com/TextureGroup/Texture/pull/668) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- Make it possible to map between sections even if they're empty [\#660](https://github.com/TextureGroup/Texture/pull/660) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASCornerLayoutSpec\] New layout spec class for declarative corner element layout. [\#657](https://github.com/TextureGroup/Texture/pull/657) ([huang-kun](https://github.com/huang-kun)) +- Update layout2-layoutspec-types.md [\#655](https://github.com/TextureGroup/Texture/pull/655) ([TBXark](https://github.com/TBXark)) +- \[Minor Breaking API\] Make deallocation queues more reliable [\#651](https://github.com/TextureGroup/Texture/pull/651) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Make the framework backwards compatible with Xcode 8 [\#650](https://github.com/TextureGroup/Texture/pull/650) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Disable this test for now, it's too flakey and no one has time to inv… [\#649](https://github.com/TextureGroup/Texture/pull/649) ([garrettmoon](https://github.com/garrettmoon)) +- \[Documentation\] Update Inversion Docs [\#647](https://github.com/TextureGroup/Texture/pull/647) ([GeekTree0101](https://github.com/GeekTree0101)) +- Have ASNetworkImageNode report whether images were cached or not [\#639](https://github.com/TextureGroup/Texture/pull/639) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix a layout deadlock caused by holding the lock and going up the tree. [\#638](https://github.com/TextureGroup/Texture/pull/638) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASScrollNode\] Fix small bugs and add unit tests [\#637](https://github.com/TextureGroup/Texture/pull/637) ([nguyenhuy](https://github.com/nguyenhuy)) +- A couple performance tweaks for animated images \#trivial [\#634](https://github.com/TextureGroup/Texture/pull/634) ([garrettmoon](https://github.com/garrettmoon)) +- \[Documentation\] Update "Getting Started" page [\#633](https://github.com/TextureGroup/Texture/pull/633) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[Tests\] Add test scrollToPageAtIndex ASPagerNode [\#629](https://github.com/TextureGroup/Texture/pull/629) ([remirobert](https://github.com/remirobert)) +- \[Tests\] Introducing tests for the ASTabBarController [\#628](https://github.com/TextureGroup/Texture/pull/628) ([remirobert](https://github.com/remirobert)) +- \[Tests\] Introducing tests for the ASNavigationController [\#627](https://github.com/TextureGroup/Texture/pull/627) ([remirobert](https://github.com/remirobert)) +- \[ASCollectionView\] Call -invalidateFlowLayoutDelegateMetrics when rotating. \#trivial [\#616](https://github.com/TextureGroup/Texture/pull/616) ([appleguy](https://github.com/appleguy)) +- Add unit tests for the layout engine [\#424](https://github.com/TextureGroup/Texture/pull/424) ([Adlai-Holler](https://github.com/Adlai-Holler)) + +## [2.5.1](https://github.com/TextureGroup/Texture/tree/2.5.1) (2017-10-24) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.5...2.5.1) + +**Merged pull requests:** + +- Dispatch batch update to main \#trivial [\#626](https://github.com/TextureGroup/Texture/pull/626) ([garrettmoon](https://github.com/garrettmoon)) +- Check if we need to do a batch update [\#624](https://github.com/TextureGroup/Texture/pull/624) ([garrettmoon](https://github.com/garrettmoon)) +- Fix naming conflict with YYText \#trivial [\#623](https://github.com/TextureGroup/Texture/pull/623) ([maicki](https://github.com/maicki)) +- Fix "This block and function declaration is not a prototype" warning. [\#619](https://github.com/TextureGroup/Texture/pull/619) ([mbesnili](https://github.com/mbesnili)) +- update Pinterest CDN URL in example code [\#613](https://github.com/TextureGroup/Texture/pull/613) ([derekargueta](https://github.com/derekargueta)) +- \[ASTextKitComponents\] Make sure Main Thread Checker isn't triggered during background calculations \#trivial [\#612](https://github.com/TextureGroup/Texture/pull/612) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASTextKitComponents\] Temporary components can be deallocated off main \#trivial [\#610](https://github.com/TextureGroup/Texture/pull/610) ([nguyenhuy](https://github.com/nguyenhuy)) +- Update layout2-layoutspec-types.md [\#608](https://github.com/TextureGroup/Texture/pull/608) ([olcayertas](https://github.com/olcayertas)) +- Don't set download results if no longer in preload range. [\#606](https://github.com/TextureGroup/Texture/pull/606) ([garrettmoon](https://github.com/garrettmoon)) +- Animated WebP support [\#605](https://github.com/TextureGroup/Texture/pull/605) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASVideoNode\] Time observer fix [\#604](https://github.com/TextureGroup/Texture/pull/604) ([flovouin](https://github.com/flovouin)) +- Add assertion in dealloc that it is on main in ASTextKitComponents \#trivial [\#603](https://github.com/TextureGroup/Texture/pull/603) ([maicki](https://github.com/maicki)) +- ASTextKitComponents needs to be deallocated on main [\#598](https://github.com/TextureGroup/Texture/pull/598) ([maicki](https://github.com/maicki)) +- update faq toc links to match the generated html id \#trivial [\#597](https://github.com/TextureGroup/Texture/pull/597) ([romankl](https://github.com/romankl)) +- \[PINCache\] Set a default .byteLimit to reduce disk usage & startup time. [\#595](https://github.com/TextureGroup/Texture/pull/595) ([appleguy](https://github.com/appleguy)) +- Move clearing out of ASTextKitComponents property delegates into ASTextKitComponents dealloc \#trivial [\#591](https://github.com/TextureGroup/Texture/pull/591) ([maicki](https://github.com/maicki)) +- Clear ivar after scheduling for main thread deallocation \#trivial [\#590](https://github.com/TextureGroup/Texture/pull/590) ([maicki](https://github.com/maicki)) +- Use Nil for "no class" instead of nil \#trivial [\#589](https://github.com/TextureGroup/Texture/pull/589) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Update showcase.md [\#587](https://github.com/TextureGroup/Texture/pull/587) ([hannahmbanana](https://github.com/hannahmbanana)) +- Rolling back CI to known version for now [\#585](https://github.com/TextureGroup/Texture/pull/585) ([garrettmoon](https://github.com/garrettmoon)) +- Use node lock instead of separate one to avoid deadlocks. [\#582](https://github.com/TextureGroup/Texture/pull/582) ([garrettmoon](https://github.com/garrettmoon)) +- \[\_ASPendingState\] Make sure accessibility strings are not nil before allocating attributed strings for them \#trivial [\#581](https://github.com/TextureGroup/Texture/pull/581) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASTextNode\] Implement an example comparing ASTextNode 1 & 2 behavior. [\#570](https://github.com/TextureGroup/Texture/pull/570) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- \[ASCollectionView\] Fix index space translation of Flow Layout Delegate methods. [\#467](https://github.com/TextureGroup/Texture/pull/467) ([appleguy](https://github.com/appleguy)) +- \[ASCollectionView\] Improve performance and behavior of rotation / bounds changes. [\#431](https://github.com/TextureGroup/Texture/pull/431) ([appleguy](https://github.com/appleguy)) + +## [2.5](https://github.com/TextureGroup/Texture/tree/2.5) (2017-09-26) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/v2.5...2.5) + +**Merged pull requests:** + +- Fix crashes caused by failing to unlock or destroy a static mutex while the app is being terminated [\#577](https://github.com/TextureGroup/Texture/pull/577) ([nguyenhuy](https://github.com/nguyenhuy)) +- Update yoga version [\#569](https://github.com/TextureGroup/Texture/pull/569) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- \[ASDKgram Example\] fix crash on startup [\#566](https://github.com/TextureGroup/Texture/pull/566) ([hannahmbanana](https://github.com/hannahmbanana)) +- Added attributed versions of accessibilityLabel, accessibilityHint, accessibilityValue [\#554](https://github.com/TextureGroup/Texture/pull/554) ([fruitcoder](https://github.com/fruitcoder)) +- \[Yoga\] Add insertYogaNode:atIndex: method. Improve handling of relayouts. [\#469](https://github.com/TextureGroup/Texture/pull/469) ([appleguy](https://github.com/appleguy)) +- \[ASCornerRounding\] Introduce .cornerRoundingType: CALayer, Precomposited, or Clip Corners. [\#465](https://github.com/TextureGroup/Texture/pull/465) ([appleguy](https://github.com/appleguy)) +- \[ASElementMap\] Fix indexPath's section or item is actually negative \#trivial [\#457](https://github.com/TextureGroup/Texture/pull/457) ([Anyewuya](https://github.com/Anyewuya)) + +## [v2.5](https://github.com/TextureGroup/Texture/tree/v2.5) (2017-09-14) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.4...v2.5) + +**Merged pull requests:** + +- Fix -\[ASPagerNode view\] triggering pendingState + nodeLoaded assert \#trivial [\#564](https://github.com/TextureGroup/Texture/pull/564) ([samhsiung](https://github.com/samhsiung)) +- \[ASCollectionLayout\] Exclude content inset on scrollable directions from viewport size [\#562](https://github.com/TextureGroup/Texture/pull/562) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASImageNode\] Always dealloc images in a background queue [\#561](https://github.com/TextureGroup/Texture/pull/561) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASCollectionNode\]\[ASTableNode\] Add content inset bridging property [\#560](https://github.com/TextureGroup/Texture/pull/560) ([nguyenhuy](https://github.com/nguyenhuy)) +- Mark ASRunLoopQueue as drained if it contains only NULLs [\#558](https://github.com/TextureGroup/Texture/pull/558) ([cesteban](https://github.com/cesteban)) +- Adds support for specifying a quality indexed array of URLs [\#557](https://github.com/TextureGroup/Texture/pull/557) ([garrettmoon](https://github.com/garrettmoon)) +- Make ASWeakMapEntry Value Atomic [\#555](https://github.com/TextureGroup/Texture/pull/555) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASDisplayNode\] Deprecate -displayWillStart in favor of -displayWillStartAsynchronously: [\#536](https://github.com/TextureGroup/Texture/pull/536) ([nguyenhuy](https://github.com/nguyenhuy)) +- SEP-491 prerequisite: add textViewShouldBeginEditing: to ASEditableTextNodeDelegate [\#535](https://github.com/TextureGroup/Texture/pull/535) ([yans](https://github.com/yans)) +- \[Gallery layout\] Include the caller in properties providing methods [\#533](https://github.com/TextureGroup/Texture/pull/533) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASDisplayNode\] Notify rasterized subnodes that render pass has completed [\#532](https://github.com/TextureGroup/Texture/pull/532) ([smeis](https://github.com/smeis)) +- \[Cleanup\] Remove deprecated APIs [\#529](https://github.com/TextureGroup/Texture/pull/529) ([nguyenhuy](https://github.com/nguyenhuy)) +- Add a function to disable all logging at runtime [\#528](https://github.com/TextureGroup/Texture/pull/528) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[Table and collection views\] Consider content inset when calculating \(default\) element size range [\#525](https://github.com/TextureGroup/Texture/pull/525) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASCollectionNode\] Add -isProcessingUpdates and -onDidFinishProcessingUpdates: APIs. [\#522](https://github.com/TextureGroup/Texture/pull/522) ([appleguy](https://github.com/appleguy)) +- ASImageNode+AnimatedImage playbackReadyCallback retain cycle [\#520](https://github.com/TextureGroup/Texture/pull/520) ([plarson](https://github.com/plarson)) +- \[CI\] BuildKite to ignore all markdown files [\#517](https://github.com/TextureGroup/Texture/pull/517) ([nguyenhuy](https://github.com/nguyenhuy)) +- ASCollectionLayout improvements [\#513](https://github.com/TextureGroup/Texture/pull/513) ([nguyenhuy](https://github.com/nguyenhuy)) +- Update changelog and podspec for 2.4 [\#512](https://github.com/TextureGroup/Texture/pull/512) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- ASCollectionLayout to return a zero content size if its state is unavailable [\#509](https://github.com/TextureGroup/Texture/pull/509) ([nguyenhuy](https://github.com/nguyenhuy)) +- Update corner-rounding.md [\#482](https://github.com/TextureGroup/Texture/pull/482) ([oferRounds](https://github.com/oferRounds)) +- \[Accessibility\] Add .isAccessibilityContainer property, allowing automatic aggregation of children's a11y labels. [\#468](https://github.com/TextureGroup/Texture/pull/468) ([appleguy](https://github.com/appleguy)) +- \[ASImageNode\] Enable .clipsToBounds by default \(fix .cornerRadius, GIFs overflow\). [\#466](https://github.com/TextureGroup/Texture/pull/466) ([appleguy](https://github.com/appleguy)) + +## [2.4](https://github.com/TextureGroup/Texture/tree/2.4) (2017-08-15) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.3.4...2.4) + +**Merged pull requests:** + +- Avoid re-entrant call to self.view when applying initial pending state [\#510](https://github.com/TextureGroup/Texture/pull/510) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[examples/ASCollectionView\] Register supplementary kinds \#trivial [\#508](https://github.com/TextureGroup/Texture/pull/508) ([nguyenhuy](https://github.com/nguyenhuy)) +- Rename the field again to nodeModel [\#504](https://github.com/TextureGroup/Texture/pull/504) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Rename -\[ASCellNode viewModel\] to -\[ASCellNode nodeViewModel\] to avoid collisions [\#499](https://github.com/TextureGroup/Texture/pull/499) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fixed typo `UIKIt` [\#497](https://github.com/TextureGroup/Texture/pull/497) ([nixzhu](https://github.com/nixzhu)) +- Improvements in ASCollectionGalleryLayoutDelegate [\#496](https://github.com/TextureGroup/Texture/pull/496) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[Showcase\] Update showcase - add blog post link to ClassDojo icon \#trivial [\#493](https://github.com/TextureGroup/Texture/pull/493) ([Kaspik](https://github.com/Kaspik)) +- \[ASCoreAnimationExtras\] Update documentation for resizbale images \#trivial [\#492](https://github.com/TextureGroup/Texture/pull/492) ([Kaspik](https://github.com/Kaspik)) +- \[ASStackLayoutSpec\] Fix interitem spacing not being reset on new lines and add snapshot tests \#trivial [\#491](https://github.com/TextureGroup/Texture/pull/491) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[Layout Transition\] Avoid calling didComplete method if pending layout transition is nil [\#490](https://github.com/TextureGroup/Texture/pull/490) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[LayoutTransition\] Call \_locked\_constrainedSizeForLayoutPass with the lock actually held \#trivial [\#488](https://github.com/TextureGroup/Texture/pull/488) ([nguyenhuy](https://github.com/nguyenhuy)) +- iOS 11 UITableView automatic height estimation fix [\#485](https://github.com/TextureGroup/Texture/pull/485) ([christianselig](https://github.com/christianselig)) +- Update scroll-node.md [\#484](https://github.com/TextureGroup/Texture/pull/484) ([oferRounds](https://github.com/oferRounds)) +- Update adoption-guide-2-0-beta1.md [\#483](https://github.com/TextureGroup/Texture/pull/483) ([oferRounds](https://github.com/oferRounds)) +- Update subclassing.md [\#479](https://github.com/TextureGroup/Texture/pull/479) ([oferRounds](https://github.com/oferRounds)) +- Invalidate layouts more aggressively when transitioning with animation [\#476](https://github.com/TextureGroup/Texture/pull/476) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Update image-modification-block.md [\#474](https://github.com/TextureGroup/Texture/pull/474) ([oferRounds](https://github.com/oferRounds)) +- \[ASStackLayoutSpec\] Flex wrap fix and lineSpacing property [\#472](https://github.com/TextureGroup/Texture/pull/472) ([flovouin](https://github.com/flovouin)) +- \[ASNodeController\] Add -nodeDidLayout callback. Allow switching retain behavior at runtime. [\#470](https://github.com/TextureGroup/Texture/pull/470) ([appleguy](https://github.com/appleguy)) +- \[Layout transition\] Invalidate calculated layout if transitioning using the same size range [\#464](https://github.com/TextureGroup/Texture/pull/464) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASTableNode\]\[ASCollectionNode\] Add content offset bridging property [\#460](https://github.com/TextureGroup/Texture/pull/460) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASDisplayNode\] Fix infinite layout loop [\#455](https://github.com/TextureGroup/Texture/pull/455) ([nguyenhuy](https://github.com/nguyenhuy)) +- Add ASPagerNode+Beta to umbrella header \#trivial [\#454](https://github.com/TextureGroup/Texture/pull/454) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASPagerNode\] Remove unused flow layout reference \#trivial [\#452](https://github.com/TextureGroup/Texture/pull/452) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASCollectionLayout\] Add ASCollectionGalleryLayoutSizeProviding [\#451](https://github.com/TextureGroup/Texture/pull/451) ([nguyenhuy](https://github.com/nguyenhuy)) +- fix SIMULATE\_WEB\_RESPONSE not imported \#449 [\#450](https://github.com/TextureGroup/Texture/pull/450) ([wsdwsd0829](https://github.com/wsdwsd0829)) +- \[ASDataController \] Merge willUpdateWithChangeSet and didUpdateWithChangeSet delegate methods \#trivial [\#445](https://github.com/TextureGroup/Texture/pull/445) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASDataController\] Clean up [\#443](https://github.com/TextureGroup/Texture/pull/443) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASDataController\] Avoid asking for size ranges of soon-to-be-delete elements during relayouts [\#442](https://github.com/TextureGroup/Texture/pull/442) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASCollectionView\] Add delegate bridging and index space translation for missing UICollectionViewLayout properties. [\#440](https://github.com/TextureGroup/Texture/pull/440) ([appleguy](https://github.com/appleguy)) +- \[ASDisplayNode\] Fix some gaps in the bridging of new contents\* properties. [\#435](https://github.com/TextureGroup/Texture/pull/435) ([appleguy](https://github.com/appleguy)) +- \[ASDisplayNode\] Allow setting stretchable contents on nodes; add bridged properties. \#trivial [\#429](https://github.com/TextureGroup/Texture/pull/429) ([appleguy](https://github.com/appleguy)) +- Use a sentinel NSUInteger for node layout data \#trivial [\#428](https://github.com/TextureGroup/Texture/pull/428) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Workaround clang4.0 \ initialization \#trivial [\#426](https://github.com/TextureGroup/Texture/pull/426) ([bkase](https://github.com/bkase)) +- Add missing import in ASDisplayNode+AsyncDisplay \#trivial [\#423](https://github.com/TextureGroup/Texture/pull/423) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASCollectionElement\] Add checks for nil element, prior to other PRs landing. [\#421](https://github.com/TextureGroup/Texture/pull/421) ([appleguy](https://github.com/appleguy)) +- \[ASDataController\] Apply new visible map inside batch updates block [\#420](https://github.com/TextureGroup/Texture/pull/420) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASVideoPlayerNode\] Check that the video player's delegate implements the didTapFullScreenButtonNode method before calling it \#trivial [\#418](https://github.com/TextureGroup/Texture/pull/418) ([tnev](https://github.com/tnev)) +- \[ASDataController\] Fix a crash in table view caused by executing an empty change set during layoutSubviews [\#416](https://github.com/TextureGroup/Texture/pull/416) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASDisplayNode+Layout\] In layoutThatFits:, check and use \_pending layout if valid. [\#413](https://github.com/TextureGroup/Texture/pull/413) ([appleguy](https://github.com/appleguy)) +- Integrate Weaver into ASDKGram [\#412](https://github.com/TextureGroup/Texture/pull/412) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASDisplayNode\] -didEnterPreloadState does not need to call -layoutIfNeeded \#trivial [\#411](https://github.com/TextureGroup/Texture/pull/411) ([appleguy](https://github.com/appleguy)) +- \[ASTextNode2\] Provide compiler flag to enable ASTextNode2 for all usages. [\#410](https://github.com/TextureGroup/Texture/pull/410) ([appleguy](https://github.com/appleguy)) +- \[Yoga\] Refine the handling of measurement functions when Yoga is used. [\#408](https://github.com/TextureGroup/Texture/pull/408) ([appleguy](https://github.com/appleguy)) +- \[ASCollectionView\] Small improvements [\#407](https://github.com/TextureGroup/Texture/pull/407) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[Documentation\] Improve description of synchronous concurrency with screenshot and video link. [\#406](https://github.com/TextureGroup/Texture/pull/406) ([appleguy](https://github.com/appleguy)) +- Introduce ASIntegerMap, improve our changeset handling \#trivial [\#405](https://github.com/TextureGroup/Texture/pull/405) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix issue where supplementary elements don't track section changes [\#404](https://github.com/TextureGroup/Texture/pull/404) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Overhaul our logging, add activity tracing support. [\#399](https://github.com/TextureGroup/Texture/pull/399) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASTextNode2\] Add initial implementation for link handling. [\#396](https://github.com/TextureGroup/Texture/pull/396) ([appleguy](https://github.com/appleguy)) +- Introduce ASCollectionGalleryLayoutDelegate [\#76](https://github.com/TextureGroup/Texture/pull/76) ([nguyenhuy](https://github.com/nguyenhuy)) + +## [2.3.4](https://github.com/TextureGroup/Texture/tree/2.3.4) (2017-06-30) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.3.3...2.3.4) + +**Merged pull requests:** + +- Update to the latest betas of PINRemoteImage and PINCache [\#403](https://github.com/TextureGroup/Texture/pull/403) ([garrettmoon](https://github.com/garrettmoon)) +- A bit of minor cleanup \#trivial [\#402](https://github.com/TextureGroup/Texture/pull/402) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASLayout\] Revisit the flattening algorithm [\#395](https://github.com/TextureGroup/Texture/pull/395) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASLayout\] If a layout has no sublayouts, don't bother initializing its rect table [\#394](https://github.com/TextureGroup/Texture/pull/394) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASLayout\] Fix documentation of retainSublayoutLayoutElements \#trivial [\#393](https://github.com/TextureGroup/Texture/pull/393) ([nguyenhuy](https://github.com/nguyenhuy)) +- Fix compiling ASDimension if Yoga enabled \#trivial [\#389](https://github.com/TextureGroup/Texture/pull/389) ([maicki](https://github.com/maicki)) +- comments to reflect code \#trivial [\#388](https://github.com/TextureGroup/Texture/pull/388) ([benjamin-chang](https://github.com/benjamin-chang)) +- \[ASCellNode\] Remove unnecessary frame setting \#trivial [\#387](https://github.com/TextureGroup/Texture/pull/387) ([nguyenhuy](https://github.com/nguyenhuy)) +- Horrible spelling mistake \#trivial [\#384](https://github.com/TextureGroup/Texture/pull/384) ([nguyenhuy](https://github.com/nguyenhuy)) +- Fix for Video Table Example Building [\#383](https://github.com/TextureGroup/Texture/pull/383) ([ay8s](https://github.com/ay8s)) +- ASDimensionMake to be more lenient \#trivial [\#382](https://github.com/TextureGroup/Texture/pull/382) ([nguyenhuy](https://github.com/nguyenhuy)) +- Gate orphaned node detector behind YOGA flag \#trivial [\#380](https://github.com/TextureGroup/Texture/pull/380) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[Event Log\] Log ASM flag when modify subnodes \#trivial [\#379](https://github.com/TextureGroup/Texture/pull/379) ([nguyenhuy](https://github.com/nguyenhuy)) +- Add new workspaces for tests for different integrations \#trivial [\#377](https://github.com/TextureGroup/Texture/pull/377) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix imageModificationBlock doc \#trivial [\#376](https://github.com/TextureGroup/Texture/pull/376) ([maicki](https://github.com/maicki)) +- Fix double-load issue with ASCollectionNode [\#372](https://github.com/TextureGroup/Texture/pull/372) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- FIXED Typo in Layout Transition Documentation [\#371](https://github.com/TextureGroup/Texture/pull/371) ([martinjkelly](https://github.com/martinjkelly)) +- \[Yoga\] Delete YOGA\_TREE\_CONTIGOUS gating and permanently enable. \#trivial [\#370](https://github.com/TextureGroup/Texture/pull/370) ([appleguy](https://github.com/appleguy)) +- \[Yoga\] Minimize number of nodes that have MeasureFunc set on them. [\#369](https://github.com/TextureGroup/Texture/pull/369) ([appleguy](https://github.com/appleguy)) +- Improve System Trace Implementation \#trivial [\#368](https://github.com/TextureGroup/Texture/pull/368) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Updates ASDKGram to use IGListKit 3.0.0 [\#367](https://github.com/TextureGroup/Texture/pull/367) ([ay8s](https://github.com/ay8s)) +- Update link to AsyncDisplayKit 2.0 Launch Talk [\#363](https://github.com/TextureGroup/Texture/pull/363) ([appleguy](https://github.com/appleguy)) +- \[ASTableView\] Use ASTableView tableNode property instead of calling ASViewToDisplayNode \#trivial [\#361](https://github.com/TextureGroup/Texture/pull/361) ([maicki](https://github.com/maicki)) +- Add section-object support to new tests, improve test confinement. \#trivial [\#360](https://github.com/TextureGroup/Texture/pull/360) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[Docs\] Update 'Corner Rounding' document for Texture 2 [\#359](https://github.com/TextureGroup/Texture/pull/359) ([ArchimboldiMao](https://github.com/ArchimboldiMao)) +- Add support for keeping letting cell nodes update to new view models when reloaded. \#trivial [\#357](https://github.com/TextureGroup/Texture/pull/357) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add first-pass view model support to collection node. \#trivial [\#356](https://github.com/TextureGroup/Texture/pull/356) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASTraitCollection\] Convert ASPrimitiveTraitCollection from lock to atomic. [\#355](https://github.com/TextureGroup/Texture/pull/355) ([appleguy](https://github.com/appleguy)) +- Improve collection node testing, reveal double-load issue. \#trivial [\#352](https://github.com/TextureGroup/Texture/pull/352) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix title in changelog [\#350](https://github.com/TextureGroup/Texture/pull/350) ([levi](https://github.com/levi)) +- Add a Flag to Disable Main Thread Assertions \#trivial [\#348](https://github.com/TextureGroup/Texture/pull/348) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Migrate to Latest OCMock, Demonstrate Improved Unit Testing [\#347](https://github.com/TextureGroup/Texture/pull/347) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Upgrade ASLayoutElementContext to an Object \#trivial [\#344](https://github.com/TextureGroup/Texture/pull/344) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[Yoga\] Rewrite YOGA\_TREE\_CONTIGUOUS mode with improved behavior and cleaner integration [\#343](https://github.com/TextureGroup/Texture/pull/343) ([appleguy](https://github.com/appleguy)) +- Fix internal Linter warnings \#trivial [\#340](https://github.com/TextureGroup/Texture/pull/340) ([maicki](https://github.com/maicki)) +- Small changes required by the coming layout debugger [\#337](https://github.com/TextureGroup/Texture/pull/337) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASDataController\] Add event logging for transaction queue flush duration \#trivial [\#334](https://github.com/TextureGroup/Texture/pull/334) ([hannahmbanana](https://github.com/hannahmbanana)) +- \[ASCollectionView\] synchronous mode [\#332](https://github.com/TextureGroup/Texture/pull/332) ([hannahmbanana](https://github.com/hannahmbanana)) +- \[Performance\] Convert ASLayoutElementSize to atomic \#trivial [\#331](https://github.com/TextureGroup/Texture/pull/331) ([hannahmbanana](https://github.com/hannahmbanana)) +- \[Yoga\] Refer to proper path name and use module import [\#306](https://github.com/TextureGroup/Texture/pull/306) ([weibel](https://github.com/weibel)) +- \[ASImageNode\] Add documentation for image effects \#trivial [\#263](https://github.com/TextureGroup/Texture/pull/263) ([maicki](https://github.com/maicki)) + +## [2.3.3](https://github.com/TextureGroup/Texture/tree/2.3.3) (2017-06-06) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.3.2...2.3.3) + +**Merged pull requests:** + +- Updating to 2.3.3 \#trivial [\#338](https://github.com/TextureGroup/Texture/pull/338) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASDisplayNode+Layout\] Add check for orphaned nodes after layout transition to clean up. [\#336](https://github.com/TextureGroup/Texture/pull/336) ([appleguy](https://github.com/appleguy)) +- Update PINRemoteImage [\#328](https://github.com/TextureGroup/Texture/pull/328) ([garrettmoon](https://github.com/garrettmoon)) +- Fix typo \#trivial [\#327](https://github.com/TextureGroup/Texture/pull/327) ([vitalybaev](https://github.com/vitalybaev)) +- Fixes an issue with GIFs that would always be covered by their placeh… [\#326](https://github.com/TextureGroup/Texture/pull/326) ([garrettmoon](https://github.com/garrettmoon)) +- Replace NSMutableSet with NSHashTable when Appropriate \#trivial [\#321](https://github.com/TextureGroup/Texture/pull/321) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[Cleanup\] Small fixes to improve conformance for strict compiler settings \#trivial [\#320](https://github.com/TextureGroup/Texture/pull/320) ([appleguy](https://github.com/appleguy)) +- Rejigger Cell Visibility Tracking [\#317](https://github.com/TextureGroup/Texture/pull/317) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Clean Up ASAsyncTransaction \#trivial [\#316](https://github.com/TextureGroup/Texture/pull/316) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Clean Up ASDisplayLayer \#trivial [\#315](https://github.com/TextureGroup/Texture/pull/315) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASDisplayNode\] Revise assertion to log until Issue \#145 is addressed. \#trivial [\#313](https://github.com/TextureGroup/Texture/pull/313) ([appleguy](https://github.com/appleguy)) +- \[Docs\] Fixed typo in carthage project name \#trivial [\#310](https://github.com/TextureGroup/Texture/pull/310) ([george-gw](https://github.com/george-gw)) +- Fix non layout [\#309](https://github.com/TextureGroup/Texture/pull/309) ([garrettmoon](https://github.com/garrettmoon)) +- Catch Invalid Layer Bounds in a Nonfatal Assertion \#trivial [\#308](https://github.com/TextureGroup/Texture/pull/308) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASCollectionNode\] Fix missing properties and layoutInspector \#trivial [\#305](https://github.com/TextureGroup/Texture/pull/305) ([flovouin](https://github.com/flovouin)) +- \[Examples\] Fixed crash on SocialAppLayout-Inverted + behaviour comments [\#304](https://github.com/TextureGroup/Texture/pull/304) ([dimazen](https://github.com/dimazen)) +- IGListKit related headers need to be in the module all time now \#trivial [\#300](https://github.com/TextureGroup/Texture/pull/300) ([maicki](https://github.com/maicki)) +- \[ASDisplayNode\] Remove assertion in calculateSizeThatFits: and log an event \#trivial [\#299](https://github.com/TextureGroup/Texture/pull/299) ([maicki](https://github.com/maicki)) +- ASBatchFetching to not round scroll velocity \#trivial [\#294](https://github.com/TextureGroup/Texture/pull/294) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[ASVideoNodeDelegate\] fix for \#291 crash [\#292](https://github.com/TextureGroup/Texture/pull/292) ([SergeyPetrachkov](https://github.com/SergeyPetrachkov)) +- Fix Alignment of Hashed Structs [\#287](https://github.com/TextureGroup/Texture/pull/287) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[IGListKit\] Add IGListKit headers to public section of Xcode project [\#286](https://github.com/TextureGroup/Texture/pull/286) ([maicki](https://github.com/maicki)) +- Only call -layout and -layoutDidFinish if the node is already loaded [\#285](https://github.com/TextureGroup/Texture/pull/285) ([nguyenhuy](https://github.com/nguyenhuy)) +- \[Batch Fetching\] Add ASBatchFetchingDelegate [\#281](https://github.com/TextureGroup/Texture/pull/281) ([nguyenhuy](https://github.com/nguyenhuy)) +- Ignore Relayout Requests for Deleted Cell Nodes [\#279](https://github.com/TextureGroup/Texture/pull/279) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Remove Unused Node Code \#trivial [\#278](https://github.com/TextureGroup/Texture/pull/278) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix Documentation Warnings \#trivial [\#276](https://github.com/TextureGroup/Texture/pull/276) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[Examples\] Fix LayoutSpecExamples and LayoutSpecExamples-Swift: image URLs were still pointing to asyncdisplaykit.org [\#275](https://github.com/TextureGroup/Texture/pull/275) ([cesteban](https://github.com/cesteban)) +- \[Layout\] Extract layout implementation code into it's own subcategories [\#272](https://github.com/TextureGroup/Texture/pull/272) ([maicki](https://github.com/maicki)) +- Fix Release Builds \#trivial [\#271](https://github.com/TextureGroup/Texture/pull/271) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[Yoga\] Implement ASYogaLayoutSpec, a simplified integration strategy for Yoga. [\#270](https://github.com/TextureGroup/Texture/pull/270) ([appleguy](https://github.com/appleguy)) +- Simplify Layout Transition State \#trivial [\#269](https://github.com/TextureGroup/Texture/pull/269) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Store ASLayoutElementContext in Thread-Local Storage \#trivial [\#268](https://github.com/TextureGroup/Texture/pull/268) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[Examples\] Fix a couple of examples due to API changes recently \#trivial [\#267](https://github.com/TextureGroup/Texture/pull/267) ([maicki](https://github.com/maicki)) +- Fix Collection Item Index Path Conversion [\#262](https://github.com/TextureGroup/Texture/pull/262) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- added error reporting callback to ASVideoNode [\#260](https://github.com/TextureGroup/Texture/pull/260) ([SergeyPetrachkov](https://github.com/SergeyPetrachkov)) +- Add Experimental Text Node Implementation [\#259](https://github.com/TextureGroup/Texture/pull/259) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add missing import and define in ASLog \#trivial [\#257](https://github.com/TextureGroup/Texture/pull/257) ([nguyenhuy](https://github.com/nguyenhuy)) +- Simplify Override Checking, Only Do It When Assertions Are Enabled \#trivial [\#253](https://github.com/TextureGroup/Texture/pull/253) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASTextKitFontSizeAdjuster\] Replace use of boundingRectWithSize:options:context: with boundingRectForGlyphRange: inTextContainer: [\#251](https://github.com/TextureGroup/Texture/pull/251) ([rcancro](https://github.com/rcancro)) +- Improve Ancestry Handling, Avoid Assertion Failure [\#246](https://github.com/TextureGroup/Texture/pull/246) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[Yoga\] Increment Yoga version to current, 1.5.0. [\#91](https://github.com/TextureGroup/Texture/pull/91) ([appleguy](https://github.com/appleguy)) +- \[example/CustomCollectionView\] Implement MosaicCollectionLayoutDelegate [\#28](https://github.com/TextureGroup/Texture/pull/28) ([nguyenhuy](https://github.com/nguyenhuy)) + +## [2.3.2](https://github.com/TextureGroup/Texture/tree/2.3.2) (2017-05-09) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.3.1...2.3.2) + +**Merged pull requests:** + +- \[ASDisplayNode\] Pass drawParameter in rendering context callbacks [\#248](https://github.com/TextureGroup/Texture/pull/248) ([maicki](https://github.com/maicki)) +- Assert only once we know URL has changed [\#247](https://github.com/TextureGroup/Texture/pull/247) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASImageNode\] Move to class method of displayWithParameters:isCancelled: for drawing [\#244](https://github.com/TextureGroup/Texture/pull/244) ([maicki](https://github.com/maicki)) +- Don't Use Associated Objects for Drawing Priority \#trivial [\#239](https://github.com/TextureGroup/Texture/pull/239) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASDimension\] Remove warning about float precision using CGFloat and … \#trivial [\#237](https://github.com/TextureGroup/Texture/pull/237) ([amegias](https://github.com/amegias)) +- \[ASImageNode\] Move debug label and will- / didDisplayNodeContentWithRenderingContext out of drawing method \#trivial [\#235](https://github.com/TextureGroup/Texture/pull/235) ([maicki](https://github.com/maicki)) +- Fixes assertion on startup in social app layout example [\#233](https://github.com/TextureGroup/Texture/pull/233) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASTextNode\] Move to class method of drawRect:withParameters:isCancelled:isRasterizing: for drawing [\#232](https://github.com/TextureGroup/Texture/pull/232) ([maicki](https://github.com/maicki)) +- \[ASImageNode\] Remove unneeded pointer star \#trivial [\#231](https://github.com/TextureGroup/Texture/pull/231) ([maicki](https://github.com/maicki)) +- \[ASTwoDimensionalArrayUtils\] Fix extern C function definition to fix compiler issue. \#trivial [\#229](https://github.com/TextureGroup/Texture/pull/229) ([appleguy](https://github.com/appleguy)) +- Move Last Few Properties from ASTableView,ASCollectionView to Node [\#225](https://github.com/TextureGroup/Texture/pull/225) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix Issues in the Project File \#trivial [\#224](https://github.com/TextureGroup/Texture/pull/224) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Improve Our Handling of Subnodes [\#223](https://github.com/TextureGroup/Texture/pull/223) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Extract ASLayoutElement and ASLayoutElementStylability into categories \#trivial [\#131](https://github.com/TextureGroup/Texture/pull/131) ([maicki](https://github.com/maicki)) +- \[Layout\] Remove finalLayoutElement [\#96](https://github.com/TextureGroup/Texture/pull/96) ([maicki](https://github.com/maicki)) +- \[Docs\] Add workaround for setting a custom lineSpacing and maxNumberOfLines to ASTextNode docs [\#92](https://github.com/TextureGroup/Texture/pull/92) ([maicki](https://github.com/maicki)) +- \[ASDisplayNode\] Implement a std::atomic-based flag system for superb performance [\#89](https://github.com/TextureGroup/Texture/pull/89) ([appleguy](https://github.com/appleguy)) +- \[Yoga\] Ensure that calculated layout is nil'd in invalidate\*Layout [\#87](https://github.com/TextureGroup/Texture/pull/87) ([appleguy](https://github.com/appleguy)) +- Simplify Hashing Code [\#86](https://github.com/TextureGroup/Texture/pull/86) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Fix site header [\#84](https://github.com/TextureGroup/Texture/pull/84) ([levi](https://github.com/levi)) +- Tighten Rasterization API, Undeprecate It [\#82](https://github.com/TextureGroup/Texture/pull/82) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Implement ASPageTable [\#81](https://github.com/TextureGroup/Texture/pull/81) ([nguyenhuy](https://github.com/nguyenhuy)) +- Make Cell Node Properties Atomic [\#74](https://github.com/TextureGroup/Texture/pull/74) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- \[ASNodeController+Beta\] Provide an option to allow nodes to own their controllers. [\#61](https://github.com/TextureGroup/Texture/pull/61) ([appleguy](https://github.com/appleguy)) +- \[Yoga Beta\] Improvements to the experimental support for Yoga layout. [\#59](https://github.com/TextureGroup/Texture/pull/59) ([appleguy](https://github.com/appleguy)) +- Fix issue with swipe to delete cell gesture. \#trivial [\#46](https://github.com/TextureGroup/Texture/pull/46) ([rewcraig](https://github.com/rewcraig)) +- Fix CustomCollectionView-Swift sample [\#22](https://github.com/TextureGroup/Texture/pull/22) ([george-gw](https://github.com/george-gw)) +- Automatically resume ASVideoNode after returning from background [\#13](https://github.com/TextureGroup/Texture/pull/13) ([plarson](https://github.com/plarson)) + +## [2.3.1](https://github.com/TextureGroup/Texture/tree/2.3.1) (2017-04-27) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.2.1...2.3.1) + +**Merged pull requests:** + +- Don't run tests for the docs directory. [\#79](https://github.com/TextureGroup/Texture/pull/79) ([garrettmoon](https://github.com/garrettmoon)) +- Fix SCSS build [\#78](https://github.com/TextureGroup/Texture/pull/78) ([levi](https://github.com/levi)) +- Fix documentation warning on ASCollectionLayoutState.h \#trivial [\#77](https://github.com/TextureGroup/Texture/pull/77) ([garrettmoon](https://github.com/garrettmoon)) +- ASLayoutSpec to use more default implementations \#trivial [\#73](https://github.com/TextureGroup/Texture/pull/73) ([nguyenhuy](https://github.com/nguyenhuy)) +- Update the CI to the new ruby version [\#71](https://github.com/TextureGroup/Texture/pull/71) ([garrettmoon](https://github.com/garrettmoon)) +- Missing a word [\#68](https://github.com/TextureGroup/Texture/pull/68) ([djblake](https://github.com/djblake)) +- Update license v2 [\#67](https://github.com/TextureGroup/Texture/pull/67) ([garrettmoon](https://github.com/garrettmoon)) +- \[ASCollectionView\] Prevent prefetching from being enabled to eliminate overhead. [\#65](https://github.com/TextureGroup/Texture/pull/65) ([appleguy](https://github.com/appleguy)) +- \[CGPointNull\] Rename globally exported C function to avoid collisions \#trivial [\#62](https://github.com/TextureGroup/Texture/pull/62) ([appleguy](https://github.com/appleguy)) +- \[RTL\] Bridge the UISemanticContentAttribute property for more convenient RTL support. [\#60](https://github.com/TextureGroup/Texture/pull/60) ([appleguy](https://github.com/appleguy)) +- Fixes a potential deadlock; it's not safe to message likely super nod… [\#56](https://github.com/TextureGroup/Texture/pull/56) ([garrettmoon](https://github.com/garrettmoon)) +- Fix \_\_has\_include check in ASLog.h \#trivial [\#55](https://github.com/TextureGroup/Texture/pull/55) ([fsmorygo](https://github.com/fsmorygo)) +- GLKit workaround \#trivial [\#54](https://github.com/TextureGroup/Texture/pull/54) ([stephenkopylov](https://github.com/stephenkopylov)) +- Layout debugger proposal [\#52](https://github.com/TextureGroup/Texture/pull/52) ([nguyenhuy](https://github.com/nguyenhuy)) +- Fixes header check to accept the 'new' header for modified files. [\#50](https://github.com/TextureGroup/Texture/pull/50) ([garrettmoon](https://github.com/garrettmoon)) +- Remove References to IGListSectionType, Now that It's Gone [\#49](https://github.com/TextureGroup/Texture/pull/49) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Move doc stylesheets to sass [\#47](https://github.com/TextureGroup/Texture/pull/47) ([levi](https://github.com/levi)) +- Fixes for Dangerfile header checks [\#45](https://github.com/TextureGroup/Texture/pull/45) ([garrettmoon](https://github.com/garrettmoon)) +- Enforce header file changes [\#44](https://github.com/TextureGroup/Texture/pull/44) ([garrettmoon](https://github.com/garrettmoon)) +- Use \_ASCollectionReusableView inside ASIGListSupplementaryViewSourceMethods [\#40](https://github.com/TextureGroup/Texture/pull/40) ([plarson](https://github.com/plarson)) +- Bump Cartfile versions to match podspec [\#37](https://github.com/TextureGroup/Texture/pull/37) ([dymv](https://github.com/dymv)) +- \[Site\] Remove hero drop shadow [\#35](https://github.com/TextureGroup/Texture/pull/35) ([levi](https://github.com/levi)) +- Add announcement banner to documentation site [\#31](https://github.com/TextureGroup/Texture/pull/31) ([levi](https://github.com/levi)) +- \[ASCollectionLayout\] Manually set size to measured cells [\#24](https://github.com/TextureGroup/Texture/pull/24) ([nguyenhuy](https://github.com/nguyenhuy)) +- Create a Pluggable "Tips" System to Help in Development [\#19](https://github.com/TextureGroup/Texture/pull/19) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Add danger [\#18](https://github.com/TextureGroup/Texture/pull/18) ([garrettmoon](https://github.com/garrettmoon)) +- Fix Case where Network Image Node Stays Locked [\#17](https://github.com/TextureGroup/Texture/pull/17) ([Adlai-Holler](https://github.com/Adlai-Holler)) +- Update the homepage URL [\#10](https://github.com/TextureGroup/Texture/pull/10) ([garrettmoon](https://github.com/garrettmoon)) + +## [2.2.1](https://github.com/TextureGroup/Texture/tree/2.2.1) (2017-04-14) +[Full Changelog](https://github.com/TextureGroup/Texture/compare/2.3...2.2.1) + +**Merged pull requests:** + +- Add blog post [\#9](https://github.com/TextureGroup/Texture/pull/9) ([garrettmoon](https://github.com/garrettmoon)) + + + +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file diff --git a/Dangerfile b/Dangerfile index 60c90dfe2e..147d389069 100644 --- a/Dangerfile +++ b/Dangerfile @@ -1,11 +1,6 @@ require 'open-uri' source_pattern = /(\.m|\.mm|\.h)$/ - -# Sometimes it's a README fix, or something like that - which isn't relevant for -# including in a project's CHANGELOG for example -declared_trivial = github.pr_title.include? "#trivial" -has_changes_in_source_directory = !git.modified_files.grep(/Source/).empty? modified_source_files = git.modified_files.grep(source_pattern) has_modified_source_files = !modified_source_files.empty? @@ -18,10 +13,9 @@ warn("PR is classed as Work in Progress") if github.pr_title.include? "[WIP]" # Warn when there is a big PR warn("This is a big PR, please consider splitting it up to ease code review.") if git.lines_of_code > 500 -# Changelog entries are required for changes to source files. -no_changelog_entry = !git.modified_files.include?("CHANGELOG.md") -if has_changes_in_source_directory && no_changelog_entry && !declared_trivial - warn("Any source code changes should have an entry in CHANGELOG.md or have #trivial in their title.") +# Modifying the changelog will probably get overwritten. +if git.modified_files.include?("CHANGELOG.md") && !github.pr_title.include?("#changelog") + warn("PR modifies CHANGELOG.md, which is a generated file. Add #changelog to the title to suppress this warning.") end def full_license(partial_license, filename) diff --git a/README.md b/README.md index 64e7f4ab33..4b939fac5a 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,10 @@ As the framework has grown, many features have been added that can save develope We use Slack for real-time debugging, community updates, and general talk about Texture. [Signup](http://asdk-slack-auto-invite.herokuapp.com) yourself or email textureframework@gmail.com to get an invite. +## Release process + +For the release process see the [RELEASE] (https://github.com/texturegroup/texture/blob/master/RELEASE.md) file. + ## Contributing We welcome any contributions. See the [CONTRIBUTING](https://github.com/texturegroup/texture/blob/master/CONTRIBUTING.md) file for how to get involved. diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000000..99ed83bfc1 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,16 @@ +# Release Process +This document describes the process for a public Texture release. + +### Preparation +- Install [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator): `sudo gem install github_changelog_generator` +- Generate a GitHub Personal Access Token to prevent running into public GitHub API rate limits: https://github.com/github-changelog-generator/github-changelog-generator#github-token + +### Process +- Run `github_changelog_generator` in Texture project directory: `github_changelog_generator --token TextureGroup/Texture` +- Update `spec.version` within `Texture.podspec`. +- Create a new PR with the updated `Texture.podspec` and the newly generated changelog, add `#changelog` to the PR message so the CI will not prevent merging it. +- After merging in the PR, [create a new GitHub release](https://github.com/TextureGroup/Texture/releases/new). Use the generated changelog for the new release. +- Update `future-release` within `.github_changelog_generator` to the next version. + +### Problems +- Sometimes we will still run into GitHub rate limit issues although using a personal token to generate the changelog. For now there is no solution for this. The issue to track is: [Triggering Github Rate limits #656](https://github.com/github-changelog-generator/github-changelog-generator/issues/656) \ No newline at end of file diff --git a/Source/ASButtonNode.mm b/Source/ASButtonNode.mm index f0ca75eed2..46bec93c51 100644 --- a/Source/ASButtonNode.mm +++ b/Source/ASButtonNode.mm @@ -63,7 +63,7 @@ _contentVerticalAlignment = ASVerticalAlignmentCenter; _contentEdgeInsets = UIEdgeInsetsZero; _imageAlignment = ASButtonNodeImageAlignmentBeginning; - self.accessibilityTraits = UIAccessibilityTraitButton; + self.accessibilityTraits = self.defaultAccessibilityTraits; } return self; } @@ -114,11 +114,7 @@ { if (self.enabled != enabled) { [super setEnabled:enabled]; - if (enabled) { - self.accessibilityTraits = UIAccessibilityTraitButton; - } else { - self.accessibilityTraits = UIAccessibilityTraitButton | UIAccessibilityTraitNotEnabled; - } + self.accessibilityTraits = self.defaultAccessibilityTraits; [self updateButtonContent]; } } @@ -204,7 +200,7 @@ _titleNode.attributedText = newTitle; [self unlock]; - self.accessibilityLabel = _titleNode.accessibilityLabel; + self.accessibilityLabel = self.defaultAccessibilityLabel; [self setNeedsLayout]; return; } @@ -544,6 +540,18 @@ return spec; } +- (NSString *)defaultAccessibilityLabel +{ + ASLockScopeSelf(); + return _titleNode.accessibilityLabel; +} + +- (UIAccessibilityTraits)defaultAccessibilityTraits +{ + return self.enabled ? UIAccessibilityTraitButton + : (UIAccessibilityTraitButton | UIAccessibilityTraitNotEnabled); +} + - (void)layout { [super layout]; diff --git a/Source/ASCGImageBuffer.m b/Source/ASCGImageBuffer.mm similarity index 99% rename from Source/ASCGImageBuffer.m rename to Source/ASCGImageBuffer.mm index 5e0c3dc921..6f05300e23 100644 --- a/Source/ASCGImageBuffer.m +++ b/Source/ASCGImageBuffer.mm @@ -1,5 +1,5 @@ // -// ASCGImageBuffer.m +// ASCGImageBuffer.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/ASCollectionNode.mm b/Source/ASCollectionNode.mm index a313ff3969..3c876caa5b 100644 --- a/Source/ASCollectionNode.mm +++ b/Source/ASCollectionNode.mm @@ -28,6 +28,7 @@ #import #import #import +#import #pragma mark - _ASCollectionPendingState @@ -63,13 +64,15 @@ self = [super init]; if (self) { _rangeMode = ASLayoutRangeModeUnspecified; - _tuningParameters = std::vector> (ASLayoutRangeModeCount, std::vector (ASLayoutRangeTypeCount, ASRangeTuningParametersZero)); + _tuningParameters = [ASAbstractLayoutController defaultTuningParameters]; _allowsSelection = YES; _allowsMultipleSelection = NO; _inverted = NO; _contentInset = UIEdgeInsetsZero; _contentOffset = CGPointZero; _animatesContentOffset = NO; + _showsVerticalScrollIndicator = YES; + _showsHorizontalScrollIndicator = YES; } return self; } @@ -221,11 +224,9 @@ let tuningParametersVectorRangeModeSize = tuningparametersRangeModeVector.size(); for (NSInteger rangeType = 0; rangeType < tuningParametersVectorRangeModeSize; rangeType++) { ASRangeTuningParameters tuningParameters = tuningparametersRangeModeVector[rangeType]; - if (!ASRangeTuningParametersEqualToRangeTuningParameters(tuningParameters, ASRangeTuningParametersZero)) { - [_rangeController setTuningParameters:tuningParameters - forRangeMode:(ASLayoutRangeMode)rangeMode - rangeType:(ASLayoutRangeType)rangeType]; - } + [_rangeController setTuningParameters:tuningParameters + forRangeMode:(ASLayoutRangeMode)rangeMode + rangeType:(ASLayoutRangeType)rangeType]; } } diff --git a/Source/ASCollectionView.mm b/Source/ASCollectionView.mm index 8c8fc853e2..fbecd3a03a 100644 --- a/Source/ASCollectionView.mm +++ b/Source/ASCollectionView.mm @@ -576,10 +576,16 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier"; - (void)_asyncDelegateOrDataSourceDidChange { ASDisplayNodeAssertMainThread(); - - if (_asyncDataSource == nil && _asyncDelegate == nil && _isDeallocating && ASActivateExperimentalFeature(ASExperimentalClearDataDuringDeallocation)) { - [_dataController clearData]; - } + + if (_asyncDataSource == nil && _asyncDelegate == nil) { + if (ASActivateExperimentalFeature(ASExperimentalClearDataDuringDeallocation)) { + if (_isDeallocating) { + [_dataController clearData]; + } + } else { + [_dataController clearData]; + } + } } - (void)setCollectionViewLayout:(nonnull UICollectionViewLayout *)collectionViewLayout diff --git a/Source/ASCollections.m b/Source/ASCollections.mm similarity index 96% rename from Source/ASCollections.m rename to Source/ASCollections.mm index 4428d07389..592dee2e88 100644 --- a/Source/ASCollections.m +++ b/Source/ASCollections.mm @@ -1,12 +1,12 @@ // -// ASCollections.m +// ASCollections.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import "ASCollections.h" +#import /** * A private allocator that signals to our retain callback to skip the retain. diff --git a/Source/ASConfiguration.m b/Source/ASConfiguration.mm similarity index 98% rename from Source/ASConfiguration.m rename to Source/ASConfiguration.mm index 7923f5837c..a973e75007 100644 --- a/Source/ASConfiguration.m +++ b/Source/ASConfiguration.mm @@ -1,5 +1,5 @@ // -// ASConfiguration.m +// ASConfiguration.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/ASConfigurationInternal.h b/Source/ASConfigurationInternal.h index 8e744e65cd..3bad3fd575 100644 --- a/Source/ASConfigurationInternal.h +++ b/Source/ASConfigurationInternal.h @@ -35,6 +35,9 @@ AS_SUBCLASSING_RESTRICTED * Just use ASActivateExperimentalFeature to access this efficiently. */ +/* Exposed for testing purposes only */ ++ (void)test_resetWithConfiguration:(nullable ASConfiguration *)configuration; + @end NS_ASSUME_NONNULL_END diff --git a/Source/ASConfigurationInternal.m b/Source/ASConfigurationInternal.mm similarity index 95% rename from Source/ASConfigurationInternal.m rename to Source/ASConfigurationInternal.mm index 4fb9685ea8..596719000c 100644 --- a/Source/ASConfigurationInternal.m +++ b/Source/ASConfigurationInternal.mm @@ -1,5 +1,5 @@ // -// ASConfigurationInternal.m +// ASConfigurationInternal.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. @@ -74,7 +74,7 @@ return NO; } - NSAssert(__builtin_popcount(requested) == 1, @"Cannot activate multiple features at once with this method."); + NSAssert(__builtin_popcountl(requested) == 1, @"Cannot activate multiple features at once with this method."); // We need to call out, whether it's enabled or not. // A/B testing requires even "control" users to be activated. diff --git a/Source/ASDisplayNode+Beta.h b/Source/ASDisplayNode+Beta.h index e140721cc6..01c08609e0 100644 --- a/Source/ASDisplayNode+Beta.h +++ b/Source/ASDisplayNode+Beta.h @@ -51,6 +51,19 @@ typedef struct { @interface ASDisplayNode (Beta) +/** + * ASTableView and ASCollectionView now throw exceptions on invalid updates + * like their UIKit counterparts. If YES, these classes will log messages + * on invalid updates rather than throwing exceptions. + * + * Note that even if AsyncDisplayKit's exception is suppressed, the app may still crash + * as it proceeds with an invalid update. + * + * This property defaults to NO. It will be removed in a future release. + */ ++ (BOOL)suppressesInvalidCollectionUpdateExceptions AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Collection update exceptions are thrown if assertions are enabled."); ++ (void)setSuppressesInvalidCollectionUpdateExceptions:(BOOL)suppresses; + /** * @abstract Recursively ensures node and all subnodes are displayed. * @see Full documentation in ASDisplayNode+FrameworkPrivate.h @@ -96,11 +109,25 @@ typedef struct { */ @property BOOL isAccessibilityContainer; +/** + * @abstract Returns the default accessibility property values set by Texture on this node. For + * example, the default accessibility label for a text node may be its text content, while most + * other nodes would have nil default labels. + */ +@property (nullable, readonly, copy) NSString *defaultAccessibilityLabel; +@property (nullable, readonly, copy) NSString *defaultAccessibilityHint; +@property (nullable, readonly, copy) NSString *defaultAccessibilityValue; +@property (nullable, readonly, copy) NSString *defaultAccessibilityIdentifier; +@property (readonly) UIAccessibilityTraits defaultAccessibilityTraits; + /** * @abstract Invoked when a user performs a custom action on an accessible node. Nodes that are children of accessibility containers, have * an accessibity label and have an interactive UIAccessibilityTrait will automatically receive custom-action handling. + * + * @return Return a boolean value that determine whether to propagate through the responder chain. + * To halt propagation, return YES; otherwise, return NO. */ -- (void)performAccessibilityCustomAction:(UIAccessibilityCustomAction *)action; +- (BOOL)performAccessibilityCustomAction:(UIAccessibilityCustomAction *)action; /** * @abstract Currently used by ASNetworkImageNode and ASMultiplexImageNode to allow their placeholders to stay if they are loading an image from the network. @@ -173,6 +200,9 @@ AS_EXTERN void ASDisplayNodePerformBlockOnEveryYogaChild(ASDisplayNode * _Nullab @property BOOL yogaLayoutInProgress; @property (nullable, nonatomic) ASLayout *yogaCalculatedLayout; +// Will walk up the Yoga tree and returns the root node +- (ASDisplayNode *)yogaRoot; + // These methods are intended to be used internally to Texture, and should not be called directly. - (BOOL)shouldHaveYogaMeasureFunc; - (void)invalidateCalculatedYogaLayout; diff --git a/Source/ASDisplayNode+Convenience.m b/Source/ASDisplayNode+Convenience.mm similarity index 96% rename from Source/ASDisplayNode+Convenience.m rename to Source/ASDisplayNode+Convenience.mm index c5d2c981ed..42ae4e4a72 100644 --- a/Source/ASDisplayNode+Convenience.m +++ b/Source/ASDisplayNode+Convenience.mm @@ -1,5 +1,5 @@ // -// ASDisplayNode+Convenience.m +// ASDisplayNode+Convenience.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/ASDisplayNode+InterfaceState.h b/Source/ASDisplayNode+InterfaceState.h index ec4414bb77..1de83700ac 100644 --- a/Source/ASDisplayNode+InterfaceState.h +++ b/Source/ASDisplayNode+InterfaceState.h @@ -116,4 +116,15 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) */ - (void)hierarchyDisplayDidFinish; +@optional +/** + * @abstract Called when the node is about to calculate layout. This is only called before + * Yoga-driven layouts. + * @discussion Can be used for operations that are performed after the node's view is available. + * @note This method is guaranteed to be called on main, but implementations should be careful not + * to attempt to ascend the node tree when handling this, as the root node is locked when this is + * called. + */ +- (void)nodeWillCalculateLayout:(ASSizeRange)constrainedSize; + @end diff --git a/Source/ASDisplayNode+Layout.mm b/Source/ASDisplayNode+Layout.mm index 532cc73e9c..9e21092c02 100644 --- a/Source/ASDisplayNode+Layout.mm +++ b/Source/ASDisplayNode+Layout.mm @@ -34,6 +34,11 @@ - (ASLayoutElementStyle *)style { ASDN::MutexLocker l(__instanceLock__); + return [self _locked_style]; +} + +- (ASLayoutElementStyle *)_locked_style +{ if (_style == nil) { _style = [[ASLayoutElementStyle alloc] init]; } @@ -295,124 +300,121 @@ ASLayoutElementStyleExtensibilityForwarding { ASAssertUnlocked(__instanceLock__); - BOOL isInLayoutPendingState = NO; - { - ASDN::MutexLocker l(__instanceLock__); - // Check if we are a subnode in a layout transition. - // In this case no measurement is needed as it's part of the layout transition - if ([self _locked_isLayoutTransitionInvalid]) { - return; - } - - CGSize boundsSizeForLayout = ASCeilSizeValues(bounds.size); - - // Prefer a newer and not yet applied _pendingDisplayNodeLayout over _calculatedDisplayNodeLayout - // If there is no such _pending, check if _calculated is valid to reuse (avoiding recalculation below). - BOOL pendingLayoutIsPreferred = NO; - if (_pendingDisplayNodeLayout.isValid(_layoutVersion)) { - NSUInteger calculatedVersion = _calculatedDisplayNodeLayout.version; - NSUInteger pendingVersion = _pendingDisplayNodeLayout.version; - if (pendingVersion > calculatedVersion) { - pendingLayoutIsPreferred = YES; // Newer _pending - } else if (pendingVersion == calculatedVersion - && !ASSizeRangeEqualToSizeRange(_pendingDisplayNodeLayout.constrainedSize, - _calculatedDisplayNodeLayout.constrainedSize)) { - pendingLayoutIsPreferred = YES; // _pending with a different constrained size - } - } - BOOL calculatedLayoutIsReusable = (_calculatedDisplayNodeLayout.isValid(_layoutVersion) - && (_calculatedDisplayNodeLayout.requestedLayoutFromAbove - || CGSizeEqualToSize(_calculatedDisplayNodeLayout.layout.size, boundsSizeForLayout))); - if (!pendingLayoutIsPreferred && calculatedLayoutIsReusable) { - return; - } - - as_activity_create_for_scope("Update node layout for current bounds"); - as_log_verbose(ASLayoutLog(), "Node %@, bounds size %@, calculatedSize %@, calculatedIsDirty %d", - self, - NSStringFromCGSize(boundsSizeForLayout), - NSStringFromCGSize(_calculatedDisplayNodeLayout->layout.size), - _calculatedDisplayNodeLayout->version < _layoutVersion); - // _calculatedDisplayNodeLayout is not reusable we need to transition to a new one - [self cancelLayoutTransition]; - - BOOL didCreateNewContext = NO; - ASLayoutElementContext *context = ASLayoutElementGetCurrentContext(); - if (context == nil) { - context = [[ASLayoutElementContext alloc] init]; - ASLayoutElementPushContext(context); - didCreateNewContext = YES; - } - - // Figure out previous and pending layouts for layout transition - ASDisplayNodeLayout nextLayout = _pendingDisplayNodeLayout; - #define layoutSizeDifferentFromBounds !CGSizeEqualToSize(nextLayout.layout.size, boundsSizeForLayout) - - // nextLayout was likely created by a call to layoutThatFits:, check if it is valid and can be applied. - // If our bounds size is different than it, or invalid, recalculate. Use #define to avoid nullptr-> - BOOL pendingLayoutApplicable = NO; - if (nextLayout.layout == nil) { - as_log_verbose(ASLayoutLog(), "No pending layout."); - } else if (!nextLayout.isValid(_layoutVersion)) { - as_log_verbose(ASLayoutLog(), "Pending layout is stale."); - } else if (layoutSizeDifferentFromBounds) { - as_log_verbose(ASLayoutLog(), "Pending layout size %@ doesn't match bounds size.", NSStringFromCGSize(nextLayout->layout.size)); - } else { - as_log_verbose(ASLayoutLog(), "Using pending layout %@.", nextLayout->layout); - pendingLayoutApplicable = YES; - } - - if (!pendingLayoutApplicable) { - as_log_verbose(ASLayoutLog(), "Measuring with previous constrained size."); - // Use the last known constrainedSize passed from a parent during layout (if never, use bounds). - NSUInteger version = _layoutVersion; - ASSizeRange constrainedSize = [self _locked_constrainedSizeForLayoutPass]; - ASLayout *layout = [self calculateLayoutThatFits:constrainedSize - restrictedToSize:self.style.size - relativeToParentSize:boundsSizeForLayout]; - nextLayout = ASDisplayNodeLayout(layout, constrainedSize, boundsSizeForLayout, version); - // Now that the constrained size of pending layout might have been reused, the layout is useless - // Release it and any orphaned subnodes it retains - _pendingDisplayNodeLayout.layout = nil; - } - - if (didCreateNewContext) { - ASLayoutElementPopContext(); - } - - // If our new layout's desired size for self doesn't match current size, ask our parent to update it. - // This can occur for either pre-calculated or newly-calculated layouts. - if (nextLayout.requestedLayoutFromAbove == NO - && CGSizeEqualToSize(boundsSizeForLayout, nextLayout.layout.size) == NO) { - as_log_verbose(ASLayoutLog(), "Layout size doesn't match bounds size. Requesting layout from above."); - // The layout that we have specifies that this node (self) would like to be a different size - // than it currently is. Because that size has been computed within the constrainedSize, we - // expect that calling setNeedsLayoutFromAbove will result in our parent resizing us to this. - // However, in some cases apps may manually interfere with this (setting a different bounds). - // In this case, we need to detect that we've already asked to be resized to match this - // particular ASLayout object, and shouldn't loop asking again unless we have a different ASLayout. - nextLayout.requestedLayoutFromAbove = YES; - - { - ASDN::MutexUnlocker u(__instanceLock__); - [self _u_setNeedsLayoutFromAbove]; - } - - // Update the layout's version here because _u_setNeedsLayoutFromAbove calls __setNeedsLayout which in turn increases _layoutVersion - // Failing to do this will cause the layout to be invalid immediately - nextLayout.version = _layoutVersion; - } - - // Prepare to transition to nextLayout - ASDisplayNodeAssertNotNil(nextLayout.layout, @"nextLayout->layout should not be nil! %@", self); - _pendingLayoutTransition = [[ASLayoutTransition alloc] initWithNode:self - pendingLayout:nextLayout - previousLayout:_calculatedDisplayNodeLayout]; - isInLayoutPendingState = ASHierarchyStateIncludesLayoutPending(_hierarchyState); + ASDN::MutexLocker l(__instanceLock__); + // Check if we are a subnode in a layout transition. + // In this case no measurement is needed as it's part of the layout transition + if ([self _locked_isLayoutTransitionInvalid]) { + return; } + CGSize boundsSizeForLayout = ASCeilSizeValues(bounds.size); + + // Prefer a newer and not yet applied _pendingDisplayNodeLayout over _calculatedDisplayNodeLayout + // If there is no such _pending, check if _calculated is valid to reuse (avoiding recalculation below). + BOOL pendingLayoutIsPreferred = NO; + if (_pendingDisplayNodeLayout.isValid(_layoutVersion)) { + NSUInteger calculatedVersion = _calculatedDisplayNodeLayout.version; + NSUInteger pendingVersion = _pendingDisplayNodeLayout.version; + if (pendingVersion > calculatedVersion) { + pendingLayoutIsPreferred = YES; // Newer _pending + } else if (pendingVersion == calculatedVersion + && !ASSizeRangeEqualToSizeRange(_pendingDisplayNodeLayout.constrainedSize, + _calculatedDisplayNodeLayout.constrainedSize)) { + pendingLayoutIsPreferred = YES; // _pending with a different constrained size + } + } + BOOL calculatedLayoutIsReusable = (_calculatedDisplayNodeLayout.isValid(_layoutVersion) + && (_calculatedDisplayNodeLayout.requestedLayoutFromAbove + || CGSizeEqualToSize(_calculatedDisplayNodeLayout.layout.size, boundsSizeForLayout))); + if (!pendingLayoutIsPreferred && calculatedLayoutIsReusable) { + return; + } + + as_activity_create_for_scope("Update node layout for current bounds"); + as_log_verbose(ASLayoutLog(), "Node %@, bounds size %@, calculatedSize %@, calculatedIsDirty %d", + self, + NSStringFromCGSize(boundsSizeForLayout), + NSStringFromCGSize(_calculatedDisplayNodeLayout->layout.size), + _calculatedDisplayNodeLayout->version < _layoutVersion); + // _calculatedDisplayNodeLayout is not reusable we need to transition to a new one + [self cancelLayoutTransition]; + + BOOL didCreateNewContext = NO; + ASLayoutElementContext *context = ASLayoutElementGetCurrentContext(); + if (context == nil) { + context = [[ASLayoutElementContext alloc] init]; + ASLayoutElementPushContext(context); + didCreateNewContext = YES; + } + + // Figure out previous and pending layouts for layout transition + ASDisplayNodeLayout nextLayout = _pendingDisplayNodeLayout; + #define layoutSizeDifferentFromBounds !CGSizeEqualToSize(nextLayout.layout.size, boundsSizeForLayout) + + // nextLayout was likely created by a call to layoutThatFits:, check if it is valid and can be applied. + // If our bounds size is different than it, or invalid, recalculate. Use #define to avoid nullptr-> + BOOL pendingLayoutApplicable = NO; + if (nextLayout.layout == nil) { + as_log_verbose(ASLayoutLog(), "No pending layout."); + } else if (!nextLayout.isValid(_layoutVersion)) { + as_log_verbose(ASLayoutLog(), "Pending layout is stale."); + } else if (layoutSizeDifferentFromBounds) { + as_log_verbose(ASLayoutLog(), "Pending layout size %@ doesn't match bounds size.", NSStringFromCGSize(nextLayout->layout.size)); + } else { + as_log_verbose(ASLayoutLog(), "Using pending layout %@.", nextLayout->layout); + pendingLayoutApplicable = YES; + } + + if (!pendingLayoutApplicable) { + as_log_verbose(ASLayoutLog(), "Measuring with previous constrained size."); + // Use the last known constrainedSize passed from a parent during layout (if never, use bounds). + NSUInteger version = _layoutVersion; + ASSizeRange constrainedSize = [self _locked_constrainedSizeForLayoutPass]; + ASLayout *layout = [self calculateLayoutThatFits:constrainedSize + restrictedToSize:self.style.size + relativeToParentSize:boundsSizeForLayout]; + nextLayout = ASDisplayNodeLayout(layout, constrainedSize, boundsSizeForLayout, version); + // Now that the constrained size of pending layout might have been reused, the layout is useless + // Release it and any orphaned subnodes it retains + _pendingDisplayNodeLayout.layout = nil; + } + + if (didCreateNewContext) { + ASLayoutElementPopContext(); + } + + // If our new layout's desired size for self doesn't match current size, ask our parent to update it. + // This can occur for either pre-calculated or newly-calculated layouts. + if (nextLayout.requestedLayoutFromAbove == NO + && CGSizeEqualToSize(boundsSizeForLayout, nextLayout.layout.size) == NO) { + as_log_verbose(ASLayoutLog(), "Layout size doesn't match bounds size. Requesting layout from above."); + // The layout that we have specifies that this node (self) would like to be a different size + // than it currently is. Because that size has been computed within the constrainedSize, we + // expect that calling setNeedsLayoutFromAbove will result in our parent resizing us to this. + // However, in some cases apps may manually interfere with this (setting a different bounds). + // In this case, we need to detect that we've already asked to be resized to match this + // particular ASLayout object, and shouldn't loop asking again unless we have a different ASLayout. + nextLayout.requestedLayoutFromAbove = YES; + + { + __instanceLock__.unlock(); + [self _u_setNeedsLayoutFromAbove]; + __instanceLock__.lock(); + } + + // Update the layout's version here because _u_setNeedsLayoutFromAbove calls __setNeedsLayout which in turn increases _layoutVersion + // Failing to do this will cause the layout to be invalid immediately + nextLayout.version = _layoutVersion; + } + + // Prepare to transition to nextLayout + ASDisplayNodeAssertNotNil(nextLayout.layout, @"nextLayout->layout should not be nil! %@", self); + _pendingLayoutTransition = [[ASLayoutTransition alloc] initWithNode:self + pendingLayout:nextLayout + previousLayout:_calculatedDisplayNodeLayout]; + // If a parent is currently executing a layout transition, perform our layout application after it. - if (isInLayoutPendingState == NO) { + if (ASHierarchyStateIncludesLayoutPending(_hierarchyState) == NO) { // If no transition, apply our new layout immediately (common case). [self _completePendingLayoutTransition]; } @@ -870,18 +872,12 @@ ASLayoutElementStyleExtensibilityForwarding */ - (void)_completePendingLayoutTransition { - ASAssertUnlocked(__instanceLock__); - - ASLayoutTransition *pendingLayoutTransition; - { - ASDN::MutexLocker l(__instanceLock__); - pendingLayoutTransition = _pendingLayoutTransition; - if (pendingLayoutTransition != nil) { - [self _locked_setCalculatedDisplayNodeLayout:pendingLayoutTransition.pendingLayout]; - } - } + __instanceLock__.lock(); + ASLayoutTransition *pendingLayoutTransition = _pendingLayoutTransition; + __instanceLock__.unlock(); if (pendingLayoutTransition != nil) { + [self _setCalculatedDisplayNodeLayout:pendingLayoutTransition.pendingLayout]; [self _completeLayoutTransition:pendingLayoutTransition]; [self _pendingLayoutTransitionDidComplete]; } @@ -901,7 +897,8 @@ ASLayoutElementStyleExtensibilityForwarding // Trampoline to the main thread if necessary if (ASDisplayNodeThreadIsMain() || layoutTransition.isSynchronous == NO) { // Committing the layout transition will result in subnode insertions and removals, both of which must be called without the lock held - ASAssertUnlocked(__instanceLock__); + // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 + // ASAssertUnlocked(__instanceLock__); [layoutTransition commitTransition]; } else { // Subnode insertions and removals need to happen always on the main thread if at least one subnode is already loaded @@ -961,7 +958,8 @@ ASLayoutElementStyleExtensibilityForwarding #endif // Subclass hook - ASAssertUnlocked(__instanceLock__); + // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 + // ASAssertUnlocked(__instanceLock__); [self calculatedLayoutDidChange]; // Grab lock after calling out to subclass @@ -997,6 +995,12 @@ ASLayoutElementStyleExtensibilityForwarding _pendingLayoutTransition = nil; } +- (void)_setCalculatedDisplayNodeLayout:(const ASDisplayNodeLayout &)displayNodeLayout +{ + ASDN::MutexLocker l(__instanceLock__); + [self _locked_setCalculatedDisplayNodeLayout:displayNodeLayout]; +} + - (void)_locked_setCalculatedDisplayNodeLayout:(const ASDisplayNodeLayout &)displayNodeLayout { ASAssertLocked(__instanceLock__); diff --git a/Source/ASDisplayNode+Yoga.mm b/Source/ASDisplayNode+Yoga.mm index 8f4cfdc63a..235db6678a 100644 --- a/Source/ASDisplayNode+Yoga.mm +++ b/Source/ASDisplayNode+Yoga.mm @@ -19,6 +19,7 @@ #import #import #import +#import #define YOGA_LAYOUT_LOGGING 0 @@ -31,8 +32,19 @@ @implementation ASDisplayNode (Yoga) +- (ASDisplayNode *)yogaRoot +{ + ASDisplayNode *yogaRoot = self; + ASDisplayNode *yogaParent = nil; + while ((yogaParent = yogaRoot.yogaParent)) { + yogaRoot = yogaParent; + } + return yogaRoot; +} + - (void)setYogaChildren:(NSArray *)yogaChildren { + ASLockScope(self.yogaRoot); for (ASDisplayNode *child in [_yogaChildren copy]) { // Make sure to un-associate the YGNodeRef tree before replacing _yogaChildren // If this becomes a performance bottleneck, it can be optimized by not doing the NSArray removals here. @@ -51,11 +63,13 @@ - (void)addYogaChild:(ASDisplayNode *)child { + ASLockScope(self.yogaRoot); [self insertYogaChild:child atIndex:_yogaChildren.count]; } - (void)removeYogaChild:(ASDisplayNode *)child { + ASLockScope(self.yogaRoot); if (child == nil) { return; } @@ -68,6 +82,7 @@ - (void)insertYogaChild:(ASDisplayNode *)child atIndex:(NSUInteger)index { + ASLockScope(self.yogaRoot); if (child == nil) { return; } @@ -216,6 +231,7 @@ - (BOOL)shouldHaveYogaMeasureFunc { // Size calculation via calculateSizeThatFits: or layoutSpecThatFits: + // For these nodes, we assume they may need custom Baseline calculation too. // This will be used for ASTextNode, as well as any other node that has no Yoga children BOOL isLeafNode = (self.yogaChildren.count == 0); BOOL definesCustomLayout = [self implementsLayoutMethod]; @@ -261,11 +277,23 @@ return; } + [self enumerateInterfaceStateDelegates:^(id _Nonnull delegate) { + if ([delegate respondsToSelector:@selector(nodeWillCalculateLayout:)]) { + [delegate nodeWillCalculateLayout:rootConstrainedSize]; + } + }]; + ASLockScopeSelf(); // Prepare all children for the layout pass with the current Yoga tree configuration. - ASDisplayNodePerformBlockOnEveryYogaChild(self, ^(ASDisplayNode * _Nonnull node) { + ASDisplayNodePerformBlockOnEveryYogaChild(self, ^(ASDisplayNode *_Nonnull node) { node.yogaLayoutInProgress = YES; + ASDisplayNode *yogaParent = node.yogaParent; + if (yogaParent) { + node.style.parentAlignStyle = yogaParent.style.alignItems; + } else { + node.style.parentAlignStyle = ASStackLayoutAlignItemsNotSet; + }; }); if (ASSizeRangeEqualToSizeRange(rootConstrainedSize, ASSizeRangeUnconstrained)) { @@ -293,7 +321,9 @@ // Reset accessible elements, since layout may have changed. ASPerformBlockOnMainThread(^{ - [(_ASDisplayView *)self.view setAccessibilityElements:nil]; + if (self.nodeLoaded && !self.isSynchronous) { + [(_ASDisplayView *)self.view setAccessibilityElements:nil]; + } }); ASDisplayNodePerformBlockOnEveryYogaChild(self, ^(ASDisplayNode * _Nonnull node) { diff --git a/Source/ASDisplayNode.mm b/Source/ASDisplayNode.mm index ff06f7f276..8f8ba56e88 100644 --- a/Source/ASDisplayNode.mm +++ b/Source/ASDisplayNode.mm @@ -78,6 +78,7 @@ NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority; @synthesize threadSafeBounds = _threadSafeBounds; +static std::atomic_bool suppressesInvalidCollectionUpdateExceptions = ATOMIC_VAR_INIT(NO); static std::atomic_bool storesUnflattenedLayouts = ATOMIC_VAR_INIT(NO); BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector) @@ -415,12 +416,13 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); - (void)onDidLoad:(ASDisplayNodeDidLoadBlock)body { - ASDN::MutexLocker l(__instanceLock__); + ASDN::UniqueLock l(__instanceLock__); if ([self _locked_isNodeLoaded]) { ASDisplayNodeAssertThreadAffinity(self); - ASDN::MutexUnlocker l(__instanceLock__); + l.unlock(); body(self); + return; } else if (_onDidLoadBlocks == nil) { _onDidLoadBlocks = [NSMutableArray arrayWithObject:body]; } else { @@ -600,7 +602,7 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); - (UIView *)view { - ASDN::MutexLocker l(__instanceLock__); + ASDN::UniqueLock l(__instanceLock__); ASDisplayNodeAssert(!_flags.layerBacked, @"Call to -view undefined on layer-backed nodes"); BOOL isLayerBacked = _flags.layerBacked; @@ -625,30 +627,28 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); // in the background on a loaded node, which isn't currently supported. if (_pendingViewState.hasSetNeedsLayout) { // Need to unlock before calling setNeedsLayout to avoid deadlocks. - // MutexUnlocker will re-lock at the end of scope. - ASDN::MutexUnlocker u(__instanceLock__); + l.unlock(); [self __setNeedsLayout]; + l.lock(); } [self _locked_applyPendingStateToViewOrLayer]; - { - // The following methods should not be called with a lock - ASDN::MutexUnlocker u(__instanceLock__); + // The following methods should not be called with a lock + l.unlock(); - // No need for the lock as accessing the subviews or layers are always happening on main - [self _addSubnodeViewsAndLayers]; - - // A subclass hook should never be called with a lock - [self _didLoad]; - } + // No need for the lock as accessing the subviews or layers are always happening on main + [self _addSubnodeViewsAndLayers]; + + // A subclass hook should never be called with a lock + [self _didLoad]; return _view; } - (CALayer *)layer { - ASDN::MutexLocker l(__instanceLock__); + ASDN::UniqueLock l(__instanceLock__); if (_layer != nil) { return _layer; } @@ -660,31 +660,30 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); // Loading a layer needs to happen on the main thread ASDisplayNodeAssertMainThread(); [self _locked_loadViewOrLayer]; + CALayer *layer = _layer; // FIXME: Ideally we'd call this as soon as the node receives -setNeedsLayout // but automatic subnode management would require us to modify the node tree // in the background on a loaded node, which isn't currently supported. if (_pendingViewState.hasSetNeedsLayout) { // Need to unlock before calling setNeedsLayout to avoid deadlocks. - // MutexUnlocker will re-lock at the end of scope. - ASDN::MutexUnlocker u(__instanceLock__); + l.unlock(); [self __setNeedsLayout]; + l.lock(); } [self _locked_applyPendingStateToViewOrLayer]; - { - // The following methods should not be called with a lock - ASDN::MutexUnlocker u(__instanceLock__); + // The following methods should not be called with a lock + l.unlock(); - // No need for the lock as accessing the subviews or layers are always happening on main - [self _addSubnodeViewsAndLayers]; - - // A subclass hook should never be called with a lock - [self _didLoad]; - } + // No need for the lock as accessing the subviews or layers are always happening on main + [self _addSubnodeViewsAndLayers]; + + // A subclass hook should never be called with a lock + [self _didLoad]; - return _layer; + return layer; } // Returns nil if the layer is not an _ASDisplayLayer; will not create the layer if nil. @@ -1032,7 +1031,7 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); BOOL loaded = NO; { - ASDN::MutexLocker l(__instanceLock__); + ASDN::UniqueLock l(__instanceLock__); loaded = [self _locked_isNodeLoaded]; CGRect bounds = _threadSafeBounds; @@ -1054,10 +1053,9 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); // This method will confirm that the layout is up to date (and update if needed). // Importantly, it will also APPLY the layout to all of our subnodes if (unless parent is transitioning). - { - ASDN::MutexUnlocker u(__instanceLock__); - [self _u_measureNodeWithBoundsIfNecessary:bounds]; - } + l.unlock(); + [self _u_measureNodeWithBoundsIfNecessary:bounds]; + l.lock(); [self _locked_layoutPlaceholderIfNecessary]; } @@ -1120,7 +1118,7 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); { __ASDisplayNodeCheckForLayoutMethodOverrides; - ASDN::MutexLocker l(__instanceLock__); + ASDN::UniqueLock l(__instanceLock__); #if YOGA // There are several cases where Yoga could arrive here: @@ -1137,11 +1135,13 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); if ([self shouldHaveYogaMeasureFunc] == NO) { // If we're a yoga root, tree node, or leaf with no measure func (e.g. spacer), then // initiate a new Yoga calculation pass from root. - ASDN::MutexUnlocker ul(__instanceLock__); + as_activity_create_for_scope("Yoga layout calculation"); if (self.yogaLayoutInProgress == NO) { ASYogaLog("Calculating yoga layout from root %@, %@", self, NSStringFromASSizeRange(constrainedSize)); + l.unlock(); [self calculateLayoutFromYogaRoot:constrainedSize]; + l.lock(); } else { ASYogaLog("Reusing existing yoga layout %@", _yogaCalculatedLayout); } @@ -2108,12 +2108,6 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { // NOTE: This method must be dealloc-safe (should not retain self). - (ASDisplayNode *)supernode { -#if CHECK_LOCKING_SAFETY - if (__instanceLock__.locked()) { - NSLog(@"WARNING: Accessing supernode while holding recursive instance lock of this node is worrisome. It's likely that you will soon try to acquire the supernode's lock, and this can easily cause deadlocks."); - } -#endif - ASDN::MutexLocker l(__instanceLock__); return _supernode; } @@ -2214,7 +2208,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { - (void)_insertSubnode:(ASDisplayNode *)subnode atSubnodeIndex:(NSInteger)subnodeIndex sublayerIndex:(NSInteger)sublayerIndex andRemoveSubnode:(ASDisplayNode *)oldSubnode { ASDisplayNodeAssertThreadAffinity(self); - ASAssertUnlocked(__instanceLock__); + // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 + // ASAssertUnlocked(__instanceLock__); as_log_verbose(ASNodeLog(), "Insert subnode %@ at index %zd of %@ and remove subnode %@", subnode, subnodeIndex, self, oldSubnode); @@ -2264,7 +2259,14 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { [_subnodes insertObject:subnode atIndex:subnodeIndex]; _cachedSubnodes = nil; __instanceLock__.unlock(); - + + if (!isRasterized && self.nodeLoaded) { + // Trigger the subnode to load its layer, which will create its view if it needs one. + // By doing this prior to downward propagation of .interfaceState in _setSupernode:, + // we can guarantee that -didEnterVisibleState is only called with .isNodeLoaded = YES. + [subnode layer]; + } + // This call will apply our .hierarchyState to the new subnode. // If we are a managed hierarchy, as in ASCellNode trees, it will also apply our .interfaceState. [subnode _setSupernode:self]; @@ -2423,7 +2425,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { - (void)_insertSubnode:(ASDisplayNode *)subnode belowSubnode:(ASDisplayNode *)below { ASDisplayNodeAssertThreadAffinity(self); - ASAssertUnlocked(__instanceLock__); + // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 + // ASAssertUnlocked(__instanceLock__); if (subnode == nil) { ASDisplayNodeFailAssert(@"Cannot insert a nil subnode"); @@ -2487,7 +2490,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { - (void)_insertSubnode:(ASDisplayNode *)subnode aboveSubnode:(ASDisplayNode *)above { ASDisplayNodeAssertThreadAffinity(self); - ASAssertUnlocked(__instanceLock__); + // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 + // ASAssertUnlocked(__instanceLock__); if (subnode == nil) { ASDisplayNodeFailAssert(@"Cannot insert a nil subnode"); @@ -2549,7 +2553,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { - (void)_insertSubnode:(ASDisplayNode *)subnode atIndex:(NSInteger)idx { ASDisplayNodeAssertThreadAffinity(self); - ASAssertUnlocked(__instanceLock__); + // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 + // ASAssertUnlocked(__instanceLock__); if (subnode == nil) { ASDisplayNodeFailAssert(@"Cannot insert a nil subnode"); @@ -2586,7 +2591,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { - (void)_removeSubnode:(ASDisplayNode *)subnode { ASDisplayNodeAssertThreadAffinity(self); - ASAssertUnlocked(__instanceLock__); + // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 + // ASAssertUnlocked(__instanceLock__); // Don't call self.supernode here because that will retain/autorelease the supernode. This method -_removeSupernode: is often called while tearing down a node hierarchy, and the supernode in question might be in the middle of its -dealloc. The supernode is never messaged, only compared by value, so this is safe. // The particular issue that triggers this edge case is when a node calls -removeFromSupernode on a subnode from within its own -dealloc method. @@ -2612,7 +2618,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { - (void)_removeFromSupernode { ASDisplayNodeAssertThreadAffinity(self); - ASAssertUnlocked(__instanceLock__); + // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 + // ASAssertUnlocked(__instanceLock__); __instanceLock__.lock(); __weak ASDisplayNode *supernode = _supernode; @@ -2626,7 +2633,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { - (void)_removeFromSupernodeIfEqualTo:(ASDisplayNode *)supernode { ASDisplayNodeAssertThreadAffinity(self); - ASAssertUnlocked(__instanceLock__); + // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 + // ASAssertUnlocked(__instanceLock__); __instanceLock__.lock(); @@ -3168,7 +3176,7 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { if (nowDisplay) { [ASDisplayNode scheduleNodeForRecursiveDisplay:self]; } else { - /*[[self asyncLayer] cancelAsyncDisplay]; + [[self asyncLayer] cancelAsyncDisplay]; //schedule clear contents on next runloop dispatch_async(dispatch_get_main_queue(), ^{ __instanceLock__.lock(); @@ -3177,7 +3185,7 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { if (ASInterfaceStateIncludesDisplay(interfaceState) == NO) { [self clearContents]; } - });*/ + }); } } } @@ -3271,10 +3279,19 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { { // subclass override ASDisplayNodeAssertMainThread(); + +#if ASDISPLAYNODE_ASSERTIONS_ENABLED + // Rasterized node's loading state is merged with root node of rasterized tree. + if (!(self.hierarchyState & ASHierarchyStateRasterized)) { + ASDisplayNodeAssert(self.isNodeLoaded, @"Node should be loaded before entering visible state."); + } +#endif + ASAssertUnlocked(__instanceLock__); [self enumerateInterfaceStateDelegates:^(id del) { [del didEnterVisibleState]; }]; + #if AS_ENABLE_TIPS [ASTipsController.shared nodeDidAppear:self]; #endif @@ -3360,7 +3377,8 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { // - If it doesn't have a calculated or pending layout that fits its current bounds, a measurement pass will occur // (see -__layout and -_u_measureNodeWithBoundsIfNecessary:). This scenario is uncommon, // and running a measurement pass here is a fine trade-off because preloading any time after this point would be late. - if (self.automaticallyManagesSubnodes) { + + if (self.automaticallyManagesSubnodes && !ASActivateExperimentalFeature(ASExperimentalDidEnterPreloadSkipASMLayout)) { [self layoutIfNeeded]; } [self enumerateInterfaceStateDelegates:^(id del) { @@ -3521,15 +3539,15 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { ASDisplayNodeAssertMainThread(); ASAssertUnlocked(__instanceLock__); - ASDN::MutexLocker l(__instanceLock__); + ASDN::UniqueLock l(__instanceLock__); // FIXME: Ideally we'd call this as soon as the node receives -setNeedsLayout // but automatic subnode management would require us to modify the node tree // in the background on a loaded node, which isn't currently supported. if (_pendingViewState.hasSetNeedsLayout) { // Need to unlock before calling setNeedsLayout to avoid deadlocks. - // MutexUnlocker will re-lock at the end of scope. - ASDN::MutexUnlocker u(__instanceLock__); + l.unlock(); [self __setNeedsLayout]; + l.lock(); } [self _locked_applyPendingViewState]; @@ -3631,6 +3649,31 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { return _isAccessibilityContainer; } +- (NSString *)defaultAccessibilityLabel +{ + return nil; +} + +- (NSString *)defaultAccessibilityHint +{ + return nil; +} + +- (NSString *)defaultAccessibilityValue +{ + return nil; +} + +- (NSString *)defaultAccessibilityIdentifier +{ + return nil; +} + +- (UIAccessibilityTraits)defaultAccessibilityTraits +{ + return UIAccessibilityTraitNone; +} + #pragma mark - Debugging (Private) #if ASEVENTLOG_ENABLE @@ -3793,6 +3836,16 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { return _unflattenedLayout; } ++ (void)setSuppressesInvalidCollectionUpdateExceptions:(BOOL)suppresses +{ + suppressesInvalidCollectionUpdateExceptions.store(suppresses); +} + ++ (BOOL)suppressesInvalidCollectionUpdateExceptions +{ + return suppressesInvalidCollectionUpdateExceptions.load(); +} + - (NSString *)displayNodeRecursiveDescription { return [self _recursiveDescriptionHelperWithIndent:@""]; diff --git a/Source/ASEditableTextNode.mm b/Source/ASEditableTextNode.mm index 18d3ce435e..19e16ae47f 100644 --- a/Source/ASEditableTextNode.mm +++ b/Source/ASEditableTextNode.mm @@ -1021,4 +1021,38 @@ [_delegate editableTextNodeDidFinishEditing:self]; } +#pragma mark - UIAccessibilityContainer + +- (NSInteger)accessibilityElementCount +{ + if (!self.isNodeLoaded) { + ASDisplayNodeFailAssert(@"Cannot access accessibilityElementCount since ASEditableTextNode is not loaded"); + return 0; + } + return 1; +} + +- (NSArray *)accessibilityElements +{ + if (!self.isNodeLoaded) { + ASDisplayNodeFailAssert(@"Cannot access accessibilityElements since ASEditableTextNode is not loaded"); + return @[]; + } + return @[self.textView]; +} + +- (id)accessibilityElementAtIndex:(NSInteger)index +{ + if (!self.isNodeLoaded) { + ASDisplayNodeFailAssert(@"Cannot access accessibilityElementAtIndex: since ASEditableTextNode is not loaded"); + return nil; + } + return self.textView; +} + +- (NSInteger)indexOfAccessibilityElement:(id)element +{ + return 0; +} + @end diff --git a/Source/ASExperimentalFeatures.h b/Source/ASExperimentalFeatures.h index 626975636c..b51523e1d8 100644 --- a/Source/ASExperimentalFeatures.h +++ b/Source/ASExperimentalFeatures.h @@ -24,6 +24,7 @@ typedef NS_OPTIONS(NSUInteger, ASExperimentalFeatures) { ASExperimentalCollectionTeardown = 1 << 6, // exp_collection_teardown ASExperimentalFramesetterCache = 1 << 7, // exp_framesetter_cache ASExperimentalClearDataDuringDeallocation = 1 << 8, // exp_clear_data_during_deallocation + ASExperimentalDidEnterPreloadSkipASMLayout = 1 << 9, // exp_did_enter_preload_skip_asm_layout ASExperimentalFeatureAll = 0xFFFFFFFF }; diff --git a/Source/ASExperimentalFeatures.m b/Source/ASExperimentalFeatures.mm similarity index 92% rename from Source/ASExperimentalFeatures.m rename to Source/ASExperimentalFeatures.mm index 73abea48b6..68a6871f04 100644 --- a/Source/ASExperimentalFeatures.m +++ b/Source/ASExperimentalFeatures.mm @@ -1,5 +1,5 @@ // -// ASExperimentalFeatures.m +// ASExperimentalFeatures.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. @@ -18,10 +18,10 @@ NSArray *ASExperimentalFeaturesGetNames(ASExperimentalFeatures flags @"exp_unfair_lock", @"exp_infer_layer_defaults", @"exp_network_image_queue", - @"exp_dealloc_queue_v2", @"exp_collection_teardown", @"exp_framesetter_cache", - @"exp_clear_data_during_deallocation"])); + @"exp_clear_data_during_deallocation", + @"exp_did_enter_preload_skip_asm_layout"])); if (flags == ASExperimentalFeatureAll) { return allNames; diff --git a/Source/ASImageNode.mm b/Source/ASImageNode.mm index 0494c90ab7..e9ddeb3ac5 100644 --- a/Source/ASImageNode.mm +++ b/Source/ASImageNode.mm @@ -442,12 +442,12 @@ typedef void (^ASImageNodeDrawParametersBlock)(ASWeakMapEntry *entry); static ASWeakMap *cache = nil; // Allocate cacheLock on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) -static ASDN::StaticMutex& cacheLock = *new ASDN::StaticMutex; +static auto *cacheLock = new ASDN::Mutex; + (ASWeakMapEntry *)contentsForkey:(ASImageNodeContentsKey *)key drawParameters:(id)drawParameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelled { { - ASDN::StaticMutexLocker l(cacheLock); + ASDN::MutexLocker l(*cacheLock); if (!cache) { cache = [[ASWeakMap alloc] init]; } @@ -464,7 +464,7 @@ static ASDN::StaticMutex& cacheLock = *new ASDN::StaticMutex; } { - ASDN::StaticMutexLocker l(cacheLock); + ASDN::MutexLocker l(*cacheLock); return [cache setObject:contents forKey:key]; } } @@ -541,8 +541,15 @@ static ASDN::StaticMutex& cacheLock = *new ASDN::StaticMutex; [super displayDidFinish]; __instanceLock__.lock(); - void (^displayCompletionBlock)(BOOL canceled) = _displayCompletionBlock; UIImage *image = _image; + void (^displayCompletionBlock)(BOOL canceled) = _displayCompletionBlock; + BOOL shouldPerformDisplayCompletionBlock = (image && displayCompletionBlock); + + // Clear the ivar now. The block is retained and will be executed shortly. + if (shouldPerformDisplayCompletionBlock) { + _displayCompletionBlock = nil; + } + BOOL hasDebugLabel = (_debugLabelNode != nil); __instanceLock__.unlock(); @@ -564,13 +571,8 @@ static ASDN::StaticMutex& cacheLock = *new ASDN::StaticMutex; } // If we've got a block to perform after displaying, do it. - if (image && displayCompletionBlock) { - + if (shouldPerformDisplayCompletionBlock) { displayCompletionBlock(NO); - - __instanceLock__.lock(); - _displayCompletionBlock = nil; - __instanceLock__.unlock(); } } diff --git a/Source/ASNavigationController.m b/Source/ASNavigationController.mm similarity index 99% rename from Source/ASNavigationController.m rename to Source/ASNavigationController.mm index a985b91c5b..c92ddd7d27 100644 --- a/Source/ASNavigationController.m +++ b/Source/ASNavigationController.mm @@ -1,5 +1,5 @@ // -// ASNavigationController.m +// ASNavigationController.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/ASNetworkImageLoadInfo.m b/Source/ASNetworkImageLoadInfo.mm similarity index 95% rename from Source/ASNetworkImageLoadInfo.m rename to Source/ASNetworkImageLoadInfo.mm index f0f0554430..4c3d553e74 100644 --- a/Source/ASNetworkImageLoadInfo.m +++ b/Source/ASNetworkImageLoadInfo.mm @@ -1,5 +1,5 @@ // -// ASNetworkImageLoadInfo.m +// ASNetworkImageLoadInfo.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/ASNetworkImageNode.h b/Source/ASNetworkImageNode.h index b32bcb0c43..049e1713a3 100644 --- a/Source/ASNetworkImageNode.h +++ b/Source/ASNetworkImageNode.h @@ -147,6 +147,15 @@ NS_ASSUME_NONNULL_BEGIN @protocol ASNetworkImageNodeDelegate @optional +/** + * Notification that the image node started to load + * + * @param imageNode The sender. + * + * @discussion Called on the main thread. + */ +- (void)imageNodeDidStartFetchingData:(ASNetworkImageNode *)imageNode; + /** * Notification that the image node finished downloading an image, with additional info. * If implemented, this method will be called instead of `imageNode:didLoadImage:`. @@ -169,15 +178,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)imageNode:(ASNetworkImageNode *)imageNode didLoadImage:(UIImage *)image; -/** - * Notification that the image node started to load - * - * @param imageNode The sender. - * - * @discussion Called on a background queue. - */ -- (void)imageNodeDidStartFetchingData:(ASNetworkImageNode *)imageNode; - /** * Notification that the image node failed to download the image. * @@ -192,6 +192,8 @@ NS_ASSUME_NONNULL_BEGIN * Notification that the image node finished decoding an image. * * @param imageNode The sender. + * + * @discussion Called on the main thread. */ - (void)imageNodeDidFinishDecoding:(ASNetworkImageNode *)imageNode; diff --git a/Source/ASNetworkImageNode.mm b/Source/ASNetworkImageNode.mm index 8a40093bc2..dea59999b0 100644 --- a/Source/ASNetworkImageNode.mm +++ b/Source/ASNetworkImageNode.mm @@ -360,9 +360,6 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); } } - // TODO: Consider removing this; it predates ASInterfaceState, which now ensures that even non-range-managed nodes get a -preload call. - [self didEnterPreloadState]; - if (self.image == nil && _downloaderFlags.downloaderImplementsSetPriority) { id downloadIdentifier = ASLockedSelf(_downloadIdentifier); if (downloadIdentifier != nil) { @@ -574,11 +571,11 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); // it and try again. { ASLockScopeSelf(); - url = _URL; + url = self->_URL; } - downloadIdentifier = [_downloader downloadImageWithURL:url + downloadIdentifier = [self->_downloader downloadImageWithURL:url callbackQueue:[self callbackQueue] downloadProgress:NULL completion:^(id _Nullable imageContainer, NSError * _Nullable error, id _Nullable downloadIdentifier, id _Nullable userInfo) { @@ -590,9 +587,9 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); { ASLockScopeSelf(); - if (ASObjectIsEqual(_URL, url)) { + if (ASObjectIsEqual(self->_URL, url)) { // The download we kicked off is correct, no need to do any more work. - _downloadIdentifier = downloadIdentifier; + self->_downloadIdentifier = downloadIdentifier; } else { // The URL changed since we kicked off our download task. This shouldn't happen often so we'll pay the cost and // cancel that request and kick off a new one. @@ -603,7 +600,7 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); if (cancelAndReattempt) { if (downloadIdentifier != nil) { as_log_verbose(ASImageLoadingLog(), "Canceling image download no resume for %@ id: %@", self, downloadIdentifier); - [_downloader cancelImageDownloadForIdentifier:downloadIdentifier]; + [self->_downloader cancelImageDownloadForIdentifier:downloadIdentifier]; } [self _downloadImageWithCompletion:finished]; return; @@ -615,6 +612,8 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); - (void)_lazilyLoadImageIfNecessary { + ASDisplayNodeAssertMainThread(); + [self lock]; __weak id delegate = _delegate; BOOL delegateDidStartFetchingData = _delegateFlags.delegateDidStartFetchingData; @@ -633,11 +632,11 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); ASLockScopeSelf(); // Bail out if not the same URL anymore - if (!ASObjectIsEqual(URL, _URL)) { + if (!ASObjectIsEqual(URL, self->_URL)) { return; } - if (_shouldCacheImage) { + if (self->_shouldCacheImage) { [self _locked__setImage:[UIImage imageNamed:URL.path.lastPathComponent]]; } else { // First try to load the path directly, for efficiency assuming a developer who @@ -654,10 +653,10 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); // If the file may be an animated gif and then created an animated image. id animatedImage = nil; - if (_downloaderFlags.downloaderImplementsAnimatedImage) { + if (self->_downloaderFlags.downloaderImplementsAnimatedImage) { let data = [[NSData alloc] initWithContentsOfURL:URL]; if (data != nil) { - animatedImage = [_downloader animatedImageWithData:data]; + animatedImage = [self->_downloader animatedImageWithData:data]; if ([animatedImage respondsToSelector:@selector(isDataSupported:)] && [animatedImage isDataSupported:data] == NO) { animatedImage = nil; @@ -672,15 +671,15 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); } } - _imageLoaded = YES; + self->_imageLoaded = YES; [self _setCurrentImageQuality:1.0]; - if (_delegateFlags.delegateDidLoadImageWithInfo) { + if (self->_delegateFlags.delegateDidLoadImageWithInfo) { ASUnlockScope(self); let info = [[ASNetworkImageLoadInfo alloc] initWithURL:URL sourceType:ASNetworkImageSourceFileURL downloadIdentifier:nil userInfo:nil]; [delegate imageNode:self didLoadImage:self.image info:info]; - } else if (_delegateFlags.delegateDidLoadImage) { + } else if (self->_delegateFlags.delegateDidLoadImage) { ASUnlockScope(self); [delegate imageNode:self didLoadImage:self.image]; } @@ -731,17 +730,17 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); void (^calloutBlock)(ASNetworkImageNode *inst); if (newImage) { - if (_delegateFlags.delegateDidLoadImageWithInfo) { + if (strongSelf->_delegateFlags.delegateDidLoadImageWithInfo) { calloutBlock = ^(ASNetworkImageNode *strongSelf) { let info = [[ASNetworkImageLoadInfo alloc] initWithURL:URL sourceType:imageSource downloadIdentifier:downloadIdentifier userInfo:userInfo]; [delegate imageNode:strongSelf didLoadImage:newImage info:info]; }; - } else if (_delegateFlags.delegateDidLoadImage) { + } else if (strongSelf->_delegateFlags.delegateDidLoadImage) { calloutBlock = ^(ASNetworkImageNode *strongSelf) { [delegate imageNode:strongSelf didLoadImage:newImage]; }; } - } else if (error && _delegateFlags.delegateDidFailWithError) { + } else if (error && strongSelf->_delegateFlags.delegateDidFailWithError) { calloutBlock = ^(ASNetworkImageNode *strongSelf) { [delegate imageNode:strongSelf didFailWithError:error]; }; @@ -755,7 +754,7 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); } }); } else { - calloutBlock(self); + calloutBlock(strongSelf); } } }); @@ -770,11 +769,11 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true); ASImageCacherCompletion completion = ^(id imageContainer) { // If the cache sentinel changed, that means this request was cancelled. - if (ASLockedSelf(_cacheSentinel != cacheSentinel)) { + if (ASLockedSelf(self->_cacheSentinel != cacheSentinel)) { return; } - if ([imageContainer asdk_image] == nil && _downloader != nil) { + if ([imageContainer asdk_image] == nil && self->_downloader != nil) { [self _downloadImageWithCompletion:^(id imageContainer, NSError *error, id downloadIdentifier, id userInfo) { finished(imageContainer, error, downloadIdentifier, ASNetworkImageSourceDownload, userInfo); }]; diff --git a/Source/ASNodeController+Beta.h b/Source/ASNodeController+Beta.h index e5bcc29622..d7f4e116e8 100644 --- a/Source/ASNodeController+Beta.h +++ b/Source/ASNodeController+Beta.h @@ -11,7 +11,8 @@ #import // for ASInterfaceState protocol /* ASNodeController is currently beta and open to change in the future */ -@interface ASNodeController<__covariant DisplayNodeType : ASDisplayNode *> : NSObject +@interface ASNodeController<__covariant DisplayNodeType : ASDisplayNode *> + : NSObject @property (nonatomic, strong /* may be weak! */) DisplayNodeType node; @@ -26,6 +27,9 @@ - (void)nodeDidLoad ASDISPLAYNODE_REQUIRES_SUPER; - (void)nodeDidLayout ASDISPLAYNODE_REQUIRES_SUPER; +// This is only called during Yoga-driven layouts. +- (void)nodeWillCalculateLayout:(ASSizeRange)constrainedSize ASDISPLAYNODE_REQUIRES_SUPER; + - (void)didEnterVisibleState ASDISPLAYNODE_REQUIRES_SUPER; - (void)didExitVisibleState ASDISPLAYNODE_REQUIRES_SUPER; diff --git a/Source/ASNodeController+Beta.mm b/Source/ASNodeController+Beta.mm index 201b3cfb93..767f23942c 100644 --- a/Source/ASNodeController+Beta.mm +++ b/Source/ASNodeController+Beta.mm @@ -7,10 +7,10 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import #import #import #import +#import #define _node (_shouldInvertStrongReference ? _weakNode : _strongNode) @@ -18,15 +18,18 @@ { ASDisplayNode *_strongNode; __weak ASDisplayNode *_weakNode; + ASDN::RecursiveMutex __instanceLock__; } - (void)loadNode { + ASLockScopeSelf(); self.node = [[ASDisplayNode alloc] init]; } - (ASDisplayNode *)node { + ASLockScopeSelf(); if (_node == nil) { [self loadNode]; } @@ -35,6 +38,7 @@ - (void)setupReferencesWithNode:(ASDisplayNode *)node { + ASLockScopeSelf(); if (_shouldInvertStrongReference) { // The node should own the controller; weak reference from controller to node. _weakNode = node; @@ -51,11 +55,13 @@ - (void)setNode:(ASDisplayNode *)node { + ASLockScopeSelf(); [self setupReferencesWithNode:node]; } - (void)setShouldInvertStrongReference:(BOOL)shouldInvertStrongReference { + ASLockScopeSelf(); if (_shouldInvertStrongReference != shouldInvertStrongReference) { // Because the BOOL controls which ivar we access, get the node before toggling. ASDisplayNode *node = _node; @@ -67,6 +73,7 @@ // subclass overrides - (void)nodeDidLoad {} - (void)nodeDidLayout {} +- (void)nodeWillCalculateLayout:(ASSizeRange)constrainedSize {} - (void)didEnterVisibleState {} - (void)didExitVisibleState {} @@ -82,11 +89,24 @@ - (void)hierarchyDisplayDidFinish {} +#pragma mark NSLocking + +- (void)lock +{ + __instanceLock__.lock(); +} + +- (void)unlock +{ + __instanceLock__.unlock(); +} + @end @implementation ASDisplayNode (ASNodeController) -- (ASNodeController *)nodeController { +- (ASNodeController *)nodeController +{ return _weakNodeController ?: _strongNodeController; } diff --git a/Source/ASPagerFlowLayout.m b/Source/ASPagerFlowLayout.mm similarity index 99% rename from Source/ASPagerFlowLayout.m rename to Source/ASPagerFlowLayout.mm index 4b24a9e39e..de20b08961 100644 --- a/Source/ASPagerFlowLayout.m +++ b/Source/ASPagerFlowLayout.mm @@ -1,5 +1,5 @@ // -// ASPagerFlowLayout.m +// ASPagerFlowLayout.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/ASPagerNode.m b/Source/ASPagerNode.mm similarity index 99% rename from Source/ASPagerNode.m rename to Source/ASPagerNode.mm index 2ab57973d7..73c9987c68 100644 --- a/Source/ASPagerNode.m +++ b/Source/ASPagerNode.mm @@ -1,5 +1,5 @@ // -// ASPagerNode.m +// ASPagerNode.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/ASRunLoopQueue.mm b/Source/ASRunLoopQueue.mm index 0463c6221b..fd88cafd80 100644 --- a/Source/ASRunLoopQueue.mm +++ b/Source/ASRunLoopQueue.mm @@ -191,7 +191,7 @@ static void runLoopSourceCallback(void *info) { #if ASRunLoopQueueLoggingEnabled - (void)checkRunLoop { - NSLog(@"<%@> - Jobs: %ld", self, _internalQueue.size()); + NSLog(@"<%@> - Jobs: %ld", self, _internalQueue.count); } #endif @@ -323,10 +323,8 @@ ASSynthesizeLockingMethodsWithMutex(_internalQueueLock) CFRunLoopRef _runLoop; CFRunLoopSourceRef _runLoopSource; CFRunLoopObserverRef _preTransactionObserver; - CFRunLoopObserverRef _postTransactionObserver; NSPointerArray *_internalQueue; ASDN::RecursiveMutex _internalQueueLock; - BOOL _CATransactionCommitInProgress; // In order to not pollute the top-level activities, each queue has 1 root activity. os_activity_t _rootActivity; @@ -343,9 +341,6 @@ ASSynthesizeLockingMethodsWithMutex(_internalQueueLock) // CoreAnimation commit order is 2000000, the goal of this is to process shortly beforehand // but after most other scheduled work on the runloop has processed. static int const kASASCATransactionQueueOrder = 1000000; -// This will mark the end of current loop and any node enqueued between kASASCATransactionQueueOrder -// and kASASCATransactionQueuePostOrder will apply interface change immediately. -static int const kASASCATransactionQueuePostOrder = 3000000; + (ASCATransactionQueue *)sharedQueue NS_RETURNS_RETAINED { @@ -377,17 +372,13 @@ static int const kASASCATransactionQueuePostOrder = 3000000; // __unsafe_unretained allows us to avoid flagging the memory cycle detector. __unsafe_unretained __typeof__(self) weakSelf = self; void (^handlerBlock) (CFRunLoopObserverRef observer, CFRunLoopActivity activity) = ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { + while (weakSelf->_internalQueue.count > 0) { [weakSelf processQueue]; - }; - void (^postHandlerBlock) (CFRunLoopObserverRef observer, CFRunLoopActivity activity) = ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { - ASDN::MutexLocker l(_internalQueueLock); - _CATransactionCommitInProgress = NO; + } }; _preTransactionObserver = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting, true, kASASCATransactionQueueOrder, handlerBlock); - _postTransactionObserver = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting, true, kASASCATransactionQueuePostOrder, postHandlerBlock); CFRunLoopAddObserver(_runLoop, _preTransactionObserver, kCFRunLoopCommonModes); - CFRunLoopAddObserver(_runLoop, _postTransactionObserver, kCFRunLoopCommonModes); // It is not guaranteed that the runloop will turn if it has no scheduled work, and this causes processing of // the queue to stop. Attaching a custom loop source to the run loop and signal it if new work needs to be done @@ -416,19 +407,14 @@ static int const kASASCATransactionQueuePostOrder = 3000000; if (CFRunLoopObserverIsValid(_preTransactionObserver)) { CFRunLoopObserverInvalidate(_preTransactionObserver); } - if (CFRunLoopObserverIsValid(_postTransactionObserver)) { - CFRunLoopObserverInvalidate(_postTransactionObserver); - } CFRelease(_preTransactionObserver); - CFRelease(_postTransactionObserver); _preTransactionObserver = nil; - _postTransactionObserver = nil; } #if ASRunLoopQueueLoggingEnabled - (void)checkRunLoop { - NSLog(@"<%@> - Jobs: %ld", self, _internalQueue.size()); + NSLog(@"<%@> - Jobs: %ld", self, _internalQueue.count); } #endif @@ -441,11 +427,6 @@ static int const kASASCATransactionQueuePostOrder = 3000000; { ASDN::MutexLocker l(_internalQueueLock); - // Mark the queue will end coalescing shortly until after CATransactionCommit. - // This will give the queue a chance to apply any further interfaceState changes/enqueue - // immediately within current runloop instead of pushing the work to next runloop cycle. - _CATransactionCommitInProgress = YES; - NSInteger internalQueueCount = _internalQueue.count; // Early-exit if the queue is empty. if (internalQueueCount == 0) { @@ -502,7 +483,7 @@ static int const kASASCATransactionQueuePostOrder = 3000000; return; } - if (!self.enabled || _CATransactionCommitInProgress) { + if (!self.enabled) { [object prepareForCATransactionCommit]; return; } diff --git a/Source/ASScrollNode.mm b/Source/ASScrollNode.mm index c155b4749b..497ef1429a 100644 --- a/Source/ASScrollNode.mm +++ b/Source/ASScrollNode.mm @@ -52,6 +52,11 @@ } } +- (NSArray *)accessibilityElements +{ + return [self.asyncdisplaykit_node accessibilityElements]; +} + @end @implementation ASScrollNode diff --git a/Source/ASTabBarController.m b/Source/ASTabBarController.mm similarity index 98% rename from Source/ASTabBarController.m rename to Source/ASTabBarController.mm index e04055ba81..c0f9e39dd3 100644 --- a/Source/ASTabBarController.m +++ b/Source/ASTabBarController.mm @@ -1,5 +1,5 @@ // -// ASTabBarController.m +// ASTabBarController.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/ASTableNode.mm b/Source/ASTableNode.mm index c17086c744..04fa78ca05 100644 --- a/Source/ASTableNode.mm +++ b/Source/ASTableNode.mm @@ -23,6 +23,7 @@ #import #import #import +#import #pragma mark - _ASTablePendingState @@ -55,7 +56,7 @@ self = [super init]; if (self) { _rangeMode = ASLayoutRangeModeUnspecified; - _tuningParameters = std::vector> (ASLayoutRangeModeCount, std::vector (ASLayoutRangeTypeCount, ASRangeTuningParametersZero)); + _tuningParameters = [ASAbstractLayoutController defaultTuningParameters]; _allowsSelection = YES; _allowsSelectionDuringEditing = NO; _allowsMultipleSelection = NO; @@ -155,6 +156,7 @@ if (_pendingState) { _ASTablePendingState *pendingState = _pendingState; + self.pendingState = nil; view.asyncDelegate = pendingState.delegate; view.asyncDataSource = pendingState.dataSource; view.inverted = pendingState.inverted; @@ -162,9 +164,17 @@ view.allowsSelectionDuringEditing = pendingState.allowsSelectionDuringEditing; view.allowsMultipleSelection = pendingState.allowsMultipleSelection; view.allowsMultipleSelectionDuringEditing = pendingState.allowsMultipleSelectionDuringEditing; - view.contentInset = pendingState.contentInset; - self.pendingState = nil; - + + UIEdgeInsets contentInset = pendingState.contentInset; + if (!UIEdgeInsetsEqualToEdgeInsets(contentInset, UIEdgeInsetsZero)) { + view.contentInset = contentInset; + } + + CGPoint contentOffset = pendingState.contentOffset; + if (!CGPointEqualToPoint(contentOffset, CGPointZero)) { + [view setContentOffset:contentOffset animated:pendingState.animatesContentOffset]; + } + let tuningParametersVector = pendingState->_tuningParameters; let tuningParametersVectorSize = tuningParametersVector.size(); for (NSInteger rangeMode = 0; rangeMode < tuningParametersVectorSize; rangeMode++) { @@ -172,19 +182,15 @@ let tuningParametersVectorRangeModeSize = tuningparametersRangeModeVector.size(); for (NSInteger rangeType = 0; rangeType < tuningParametersVectorRangeModeSize; rangeType++) { ASRangeTuningParameters tuningParameters = tuningparametersRangeModeVector[rangeType]; - if (!ASRangeTuningParametersEqualToRangeTuningParameters(tuningParameters, ASRangeTuningParametersZero)) { - [_rangeController setTuningParameters:tuningParameters - forRangeMode:(ASLayoutRangeMode)rangeMode - rangeType:(ASLayoutRangeType)rangeType]; - } + [_rangeController setTuningParameters:tuningParameters + forRangeMode:(ASLayoutRangeMode)rangeMode + rangeType:(ASLayoutRangeType)rangeType]; } } if (pendingState.rangeMode != ASLayoutRangeModeUnspecified) { [_rangeController updateCurrentRangeWithMode:pendingState.rangeMode]; } - - [view setContentOffset:pendingState.contentOffset animated:pendingState.animatesContentOffset]; } } diff --git a/Source/ASTableView.mm b/Source/ASTableView.mm index 81e0527dd7..920241f473 100644 --- a/Source/ASTableView.mm +++ b/Source/ASTableView.mm @@ -437,6 +437,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; _dataController.validationErrorSource = asyncDataSource; super.dataSource = (id)_proxyDataSource; + [self _asyncDelegateOrDataSourceDidChange]; } - (id)asyncDelegate @@ -507,6 +508,22 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; } super.delegate = (id)_proxyDelegate; + [self _asyncDelegateOrDataSourceDidChange]; +} + +- (void)_asyncDelegateOrDataSourceDidChange +{ + ASDisplayNodeAssertMainThread(); + + if (_asyncDataSource == nil && _asyncDelegate == nil) { + if (ASActivateExperimentalFeature(ASExperimentalClearDataDuringDeallocation)) { + if (_isDeallocating) { + [_dataController clearData]; + } + } else { + [_dataController clearData]; + } + } } - (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy diff --git a/Source/ASTextNode+Beta.h b/Source/ASTextNode+Beta.h index 09259bd7f4..ad897c5f0e 100644 --- a/Source/ASTextNode+Beta.h +++ b/Source/ASTextNode+Beta.h @@ -35,6 +35,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (readonly) BOOL usingExperiment; +/** + * Returns a Boolean indicating if the text node will truncate for the given constrained size + */ +- (BOOL)shouldTruncateForConstrainedSize:(ASSizeRange)constrainedSize; + @end NS_ASSUME_NONNULL_END diff --git a/Source/ASTextNode.h b/Source/ASTextNode.h index b6c676a3a6..1048017e79 100644 --- a/Source/ASTextNode.h +++ b/Source/ASTextNode.h @@ -217,6 +217,15 @@ NS_ASSUME_NONNULL_BEGIN @end +/** + * @abstract Text node unsupported properties + */ +@interface ASTextNode (Unsupported) + +@property (nullable, nonatomic) id textContainerLinePositionModifier; + +@end + /** * @abstract Text node deprecated properties */ diff --git a/Source/ASTextNode.mm b/Source/ASTextNode.mm index 1de1117dd9..1cf8489c80 100644 --- a/Source/ASTextNode.mm +++ b/Source/ASTextNode.mm @@ -226,7 +226,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; // Accessibility self.isAccessibilityElement = YES; - self.accessibilityTraits = UIAccessibilityTraitStaticText; + self.accessibilityTraits = self.defaultAccessibilityTraits; // Placeholders // Disabled by default in ASDisplayNode, but add a few options for those who toggle @@ -365,6 +365,17 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; }; } +- (NSString *)defaultAccessibilityLabel +{ + ASLockScopeSelf(); + return _attributedText.string; +} + +- (UIAccessibilityTraits)defaultAccessibilityTraits +{ + return UIAccessibilityTraitStaticText; +} + #pragma mark - Layout and Sizing - (void)setTextContainerInset:(UIEdgeInsets)textContainerInset @@ -440,39 +451,46 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; if (attributedText == nil) { attributedText = [[NSAttributedString alloc] initWithString:@"" attributes:nil]; } - - // Don't hold textLock for too long. + { ASLockScopeSelf(); if (ASObjectIsEqual(attributedText, _attributedText)) { return; } - _attributedText = ASCleanseAttributedStringOfCoreTextAttributes(attributedText); -#if AS_TEXTNODE_RECORD_ATTRIBUTED_STRINGS - [ASTextNode _registerAttributedText:_attributedText]; -#endif - } - - // Since truncation text matches style of attributedText, invalidate it now. - [self _invalidateTruncationText]; - - NSUInteger length = _attributedText.length; - if (length > 0) { - self.style.ascender = [[self class] ascenderWithAttributedString:_attributedText]; - self.style.descender = [[_attributedText attribute:NSFontAttributeName atIndex:length - 1 effectiveRange:NULL] descender]; - } + NSAttributedString *cleanedAttributedString = ASCleanseAttributedStringOfCoreTextAttributes(attributedText); + // Invalidating the truncation text must be done while we still hold the lock. Because after we release it, + // another thread may set a new truncation text that will then be cleared by this thread, other may draw + // this soon-to-be-invalidated text. + [self _locked_invalidateTruncationText]; + + NSUInteger length = cleanedAttributedString.length; + if (length > 0) { + // Updating ascender and descender in one transaction while holding the lock. + ASLayoutElementStyle *style = [self _locked_style]; + style.ascender = [[self class] ascenderWithAttributedString:cleanedAttributedString]; + style.descender = [[attributedText attribute:NSFontAttributeName atIndex:cleanedAttributedString.length - 1 effectiveRange:NULL] descender]; + } + + // Update attributed text with cleaned attributed string + _attributedText = cleanedAttributedString; + } + // Tell the display node superclasses that the cached layout is incorrect now [self setNeedsLayout]; // Force display to create renderer with new size and redisplay with new string [self setNeedsDisplay]; - // Accessiblity - self.accessibilityLabel = _attributedText.string; - self.isAccessibilityElement = (length != 0); // We're an accessibility element by default if there is a string. + let currentAttributedText = self.attributedText; // Grab attributed string again in case it changed in the meantime + self.accessibilityLabel = self.defaultAccessibilityLabel; + self.isAccessibilityElement = (currentAttributedText.length != 0); // We're an accessibility element by default if there is a string. + +#if AS_TEXTNODE_RECORD_ATTRIBUTED_STRINGS + [ASTextNode _registerAttributedText:_attributedText]; +#endif } #pragma mark - Text Layout @@ -589,7 +607,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; return; } - for (NSString *attributeName in _linkAttributeNames) { + for (NSString *attributeName in self->_linkAttributeNames) { NSRange range; id value = [attributedString attribute:attributeName atIndex:characterIndex longestEffectiveRange:&range inRange:clampedRange]; NSString *name = attributeName; @@ -601,8 +619,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; // If highlighting, check with delegate first. If not implemented, assume YES. if (highlighting - && [_delegate respondsToSelector:@selector(textNode:shouldHighlightLinkAttribute:value:atPoint:)] - && ![_delegate textNode:self shouldHighlightLinkAttribute:name value:value atPoint:point]) { + && [self->_delegate respondsToSelector:@selector(textNode:shouldHighlightLinkAttribute:value:atPoint:)] + && ![self->_delegate textNode:self shouldHighlightLinkAttribute:name value:value atPoint:point]) { value = nil; name = nil; } @@ -955,9 +973,7 @@ static CGRect ASTextNodeAdjustRenderRectForShadowPadding(CGRect rendererRect, UI NSUInteger lastCharIndex = NSIntegerMax; BOOL linkCrossesVisibleRange = (lastCharIndex > range.location) && (lastCharIndex < NSMaxRange(range) - 1); - if (inAdditionalTruncationMessage) { - return YES; - } else if (range.length && !linkCrossesVisibleRange && linkAttributeValue != nil && linkAttributeName != nil) { + if (range.length > 0 && !linkCrossesVisibleRange && linkAttributeValue != nil && linkAttributeName != nil) { return YES; } else { return NO; @@ -993,7 +1009,7 @@ static CGRect ASTextNodeAdjustRenderRectForShadowPadding(CGRect rendererRect, UI } NSRange truncationMessageRange = [self _additionalTruncationMessageRangeWithVisibleRange:visibleRange]; [self _setHighlightRange:truncationMessageRange forAttributeName:ASTextNodeTruncationTokenAttributeName value:nil animated:YES]; - } else if (range.length && !linkCrossesVisibleRange && linkAttributeValue != nil && linkAttributeName != nil) { + } else if (range.length > 0 && !linkCrossesVisibleRange && linkAttributeValue != nil && linkAttributeName != nil) { [self _setHighlightRange:range forAttributeName:linkAttributeName value:linkAttributeValue animated:YES]; } } @@ -1166,6 +1182,7 @@ static NSAttributedString *DefaultTruncationAttributedString() { if (ASLockedSelfCompareAssignCopy(_truncationAttributedText, truncationAttributedText)) { [self _invalidateTruncationText]; + [self setNeedsDisplay]; } } @@ -1173,6 +1190,7 @@ static NSAttributedString *DefaultTruncationAttributedString() { if (ASLockedSelfCompareAssignCopy(_additionalTruncationMessage, additionalTruncationMessage)) { [self _invalidateTruncationText]; + [self setNeedsDisplay]; } } @@ -1198,6 +1216,11 @@ static NSAttributedString *DefaultTruncationAttributedString() return ASLockedSelf([[self _locked_renderer] isTruncated]); } +- (BOOL)shouldTruncateForConstrainedSize:(ASSizeRange)constrainedSize +{ + return ASLockedSelf([[self _locked_rendererWithBounds:{.size = constrainedSize.max}] isTruncated]); +} + - (void)setPointSizeScaleFactors:(NSArray *)pointSizeScaleFactors { if (ASLockedSelfCompareAssignCopy(_pointSizeScaleFactors, pointSizeScaleFactors)) { @@ -1231,12 +1254,13 @@ static NSAttributedString *DefaultTruncationAttributedString() - (void)_invalidateTruncationText { - { - ASLockScopeSelf(); - _composedTruncationText = nil; - } + ASLockScopeSelf(); + [self _locked_invalidateTruncationText]; +} - [self setNeedsDisplay]; +- (void)_locked_invalidateTruncationText +{ + _composedTruncationText = nil; } /** @@ -1365,6 +1389,21 @@ static NSAttributedString *DefaultTruncationAttributedString() @end +@implementation ASTextNode (Unsupported) + +- (void)setTextContainerLinePositionModifier:(id)textContainerLinePositionModifier +{ + AS_TEXT_ALERT_UNIMPLEMENTED_FEATURE(); +} + +- (id)textContainerLinePositionModifier +{ + AS_TEXT_ALERT_UNIMPLEMENTED_FEATURE(); + return nil; +} + +@end + @implementation ASTextNode (Deprecated) - (void)setAttributedString:(NSAttributedString *)attributedString diff --git a/Source/ASTextNode2.h b/Source/ASTextNode2.h index 7718672515..442a476025 100644 --- a/Source/ASTextNode2.h +++ b/Source/ASTextNode2.h @@ -9,6 +9,8 @@ #import #import +@protocol ASTextLinePositionModifier; + NS_ASSUME_NONNULL_BEGIN /** @@ -207,6 +209,10 @@ NS_ASSUME_NONNULL_BEGIN + (void)enableDebugging; +#pragma mark - Layout and Sizing + +@property (nullable, nonatomic) id textContainerLinePositionModifier; + @end @interface ASTextNode2 (Unavailable) diff --git a/Source/ASTextNode2.mm b/Source/ASTextNode2.mm index aaa215e672..f3ec51fa35 100644 --- a/Source/ASTextNode2.mm +++ b/Source/ASTextNode2.mm @@ -48,11 +48,93 @@ */ #define AS_TEXTNODE2_RECORD_ATTRIBUTED_STRINGS 0 -#define AS_TEXT_ALERT_UNIMPLEMENTED_FEATURE() { \ - static dispatch_once_t onceToken; \ - dispatch_once(&onceToken, ^{ \ - NSLog(@"[Texture] Warning: Feature %@ is unimplemented in the experimental text node.", NSStringFromSelector(_cmd)); \ - });\ +/** + * If it can't find a compatible layout, this method creates one. + * + * NOTE: Be careful to copy `text` if needed. + */ +static NS_RETURNS_RETAINED ASTextLayout *ASTextNodeCompatibleLayoutWithContainerAndText(ASTextContainer *container, NSAttributedString *text) { + // Allocate layoutCacheLock on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) + static auto *layoutCacheLock = new ASDN::Mutex; + static NSCache *textLayoutCache; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + textLayoutCache = [[NSCache alloc] init]; + }); + + layoutCacheLock->lock(); + + ASTextCacheValue *cacheValue = [textLayoutCache objectForKey:text]; + if (cacheValue == nil) { + cacheValue = [[ASTextCacheValue alloc] init]; + [textLayoutCache setObject:cacheValue forKey:[text copy]]; + } + + // Lock the cache item for the rest of the method. Only after acquiring can we release the NSCache. + ASDN::MutexLocker lock(cacheValue->_m); + layoutCacheLock->unlock(); + + CGRect containerBounds = (CGRect){ .size = container.size }; + { + for (let &t : cacheValue->_layouts) { + CGSize constrainedSize = std::get<0>(t); + ASTextLayout *layout = std::get<1>(t); + + CGSize layoutSize = layout.textBoundingSize; + // 1. CoreText can return frames that are narrower than the constrained width, for obvious reasons. + // 2. CoreText can return frames that are slightly wider than the constrained width, for some reason. + // We have to trust that somehow it's OK to try and draw within our size constraint, despite the return value. + // 3. Thus, those two values (constrained width & returned width) form a range, where + // intermediate values in that range will be snapped. Thus, we can use a given layout as long as our + // width is in that range, between the min and max of those two values. + CGRect minRect = CGRectMake(0, 0, MIN(layoutSize.width, constrainedSize.width), MIN(layoutSize.height, constrainedSize.height)); + if (!CGRectContainsRect(containerBounds, minRect)) { + continue; + } + CGRect maxRect = CGRectMake(0, 0, MAX(layoutSize.width, constrainedSize.width), MAX(layoutSize.height, constrainedSize.height)); + if (!CGRectContainsRect(maxRect, containerBounds)) { + continue; + } + if (!CGSizeEqualToSize(container.size, constrainedSize)) { + continue; + } + + // Now check container params. + ASTextContainer *otherContainer = layout.container; + if (!UIEdgeInsetsEqualToEdgeInsets(container.insets, otherContainer.insets)) { + continue; + } + if (!ASObjectIsEqual(container.exclusionPaths, otherContainer.exclusionPaths)) { + continue; + } + if (container.maximumNumberOfRows != otherContainer.maximumNumberOfRows) { + continue; + } + if (container.truncationType != otherContainer.truncationType) { + continue; + } + if (!ASObjectIsEqual(container.truncationToken, otherContainer.truncationToken)) { + continue; + } + // TODO: When we get a cache hit, move this entry to the front (LRU). + return layout; + } + } + + // Cache Miss. Compute the text layout. + ASTextLayout *layout = [ASTextLayout layoutWithContainer:container text:text]; + + // Store the result in the cache. + { + // This is a critical section. However we also must hold the lock until this point, in case + // another thread requests this cache item while a layout is being calculated, so they don't race. + cacheValue->_layouts.push_front(std::make_tuple(container.size, layout)); + if (cacheValue->_layouts.size() > 3) { + cacheValue->_layouts.pop_back(); + } + } + + return layout; } static const CGFloat ASTextNodeHighlightLightOpacity = 0.11; @@ -115,7 +197,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; // Accessibility self.isAccessibilityElement = YES; - self.accessibilityTraits = UIAccessibilityTraitStaticText; + self.accessibilityTraits = self.defaultAccessibilityTraits; // Placeholders // Disabled by default in ASDisplayNode, but add a few options for those who toggle @@ -209,6 +291,17 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; return YES; } +- (NSString *)defaultAccessibilityLabel +{ + ASLockScopeSelf(); + return _attributedText.string; +} + +- (UIAccessibilityTraits)defaultAccessibilityTraits +{ + return UIAccessibilityTraitStaticText; +} + #pragma mark - Layout and Sizing - (void)setTextContainerInset:(UIEdgeInsets)textContainerInset @@ -225,6 +318,17 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; return _textContainer.insets; } +- (void)setTextContainerLinePositionModifier:(id)modifier +{ + ASLockedSelfCompareAssignObjects(_textContainer.linePositionModifier, modifier); +} + +- (id)textContainerLinePositionModifier +{ + ASLockScopeSelf(); + return _textContainer.linePositionModifier; +} + - (CGSize)calculateSizeThatFits:(CGSize)constrainedSize { ASDisplayNodeAssert(constrainedSize.width >= 0, @"Constrained width for text (%f) is too narrow", constrainedSize.width); @@ -234,11 +338,19 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; _textContainer.size = constrainedSize; [self _ensureTruncationText]; - + + // If the constrained size has a max/inf value on the text's forward direction, the text node is calculating its intrinsic size. + // Need to consider both width and height when determining if it is calculating instrinsic size. Even the constrained width is provided, the height can be inf + // it may provide a text that is longer than the width and require a wordWrapping line break mode and looking for the height to be calculated. + BOOL isCalculatingIntrinsicSize = (_textContainer.size.width >= ASTextContainerMaxSize.width) || (_textContainer.size.height >= ASTextContainerMaxSize.height); + NSMutableAttributedString *mutableText = [_attributedText mutableCopy]; - [self prepareAttributedString:mutableText]; - ASTextLayout *layout = [ASTextNode2 compatibleLayoutWithContainer:_textContainer text:mutableText]; - + [self prepareAttributedString:mutableText isForIntrinsicSize:isCalculatingIntrinsicSize]; + ASTextLayout *layout = ASTextNodeCompatibleLayoutWithContainerAndText(_textContainer, mutableText); + if (layout.truncatedLine != nil && layout.truncatedLine.size.width > layout.textBoundingSize.width) { + return (CGSize) {MIN(constrainedSize.width, layout.truncatedLine.size.width), layout.textBoundingSize.height}; + } + return layout.textBoundingSize; } @@ -280,12 +392,13 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; } // Since truncation text matches style of attributedText, invalidate it now. - [self _invalidateTruncationText]; - + [self _locked_invalidateTruncationText]; + NSUInteger length = attributedText.length; if (length > 0) { - self.style.ascender = [[self class] ascenderWithAttributedString:attributedText]; - self.style.descender = [[attributedText attribute:NSFontAttributeName atIndex:attributedText.length - 1 effectiveRange:NULL] descender]; + ASLayoutElementStyle *style = [self _locked_style]; + style.ascender = [[self class] ascenderWithAttributedString:attributedText]; + style.descender = [[attributedText attribute:NSFontAttributeName atIndex:attributedText.length - 1 effectiveRange:NULL] descender]; } // Tell the display node superclasses that the cached layout is incorrect now @@ -295,7 +408,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; [self setNeedsDisplay]; // Accessiblity - self.accessibilityLabel = attributedText.string; + self.accessibilityLabel = self.defaultAccessibilityLabel; self.isAccessibilityElement = (length != 0); // We're an accessibility element by default if there is a string. #if AS_TEXTNODE2_RECORD_ATTRIBUTED_STRINGS @@ -320,21 +433,56 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; return _textContainer.exclusionPaths; } -- (void)prepareAttributedString:(NSMutableAttributedString *)attributedString +- (void)prepareAttributedString:(NSMutableAttributedString *)attributedString isForIntrinsicSize:(BOOL)isForIntrinsicSize { ASLockScopeSelf(); - - // Apply paragraph style if needed + NSLineBreakMode innerMode; + switch (_truncationMode) { + case NSLineBreakByWordWrapping: + case NSLineBreakByCharWrapping: + case NSLineBreakByClipping: + innerMode = _truncationMode; + break; + default: + innerMode = NSLineBreakByWordWrapping; + } + + // Apply/Fix paragraph style if needed [attributedString enumerateAttribute:NSParagraphStyleAttributeName inRange:NSMakeRange(0, attributedString.length) options:kNilOptions usingBlock:^(NSParagraphStyle *style, NSRange range, BOOL * _Nonnull stop) { - if (style == nil || style.lineBreakMode == _truncationMode) { + + BOOL applyTruncationMode = YES; + NSMutableParagraphStyle *paragraphStyle = nil; + // Only "left" and "justified" alignments are supported while calculating intrinsic size. + // Other alignments like "right", "center" and "natural" cause the size to be bigger than needed and thus should be ignored/overridden. + const BOOL forceLeftAlignment = (style != nil + && isForIntrinsicSize + && style.alignment != NSTextAlignmentLeft + && style.alignment != NSTextAlignmentJustified); + if (style != nil) { + if (innerMode == style.lineBreakMode) { + applyTruncationMode = NO; + } + paragraphStyle = [style mutableCopy]; + } else { + if (innerMode == NSLineBreakByWordWrapping) { + applyTruncationMode = NO; + } + paragraphStyle = [NSMutableParagraphStyle new]; + } + if (!applyTruncationMode && !forceLeftAlignment) { return; } - - NSMutableParagraphStyle *paragraphStyle = [style mutableCopy] ?: [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineBreakMode = _truncationMode; + paragraphStyle.lineBreakMode = innerMode; + + if (applyTruncationMode) { + paragraphStyle.lineBreakMode = _truncationMode; + } + if (forceLeftAlignment) { + paragraphStyle.alignment = NSTextAlignmentLeft; + } [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range]; }]; - + // Apply shadow if needed if (_shadowOpacity > 0 && (_shadowRadius != 0 || !CGSizeEqualToSize(_shadowOffset, CGSizeZero)) && CGColorGetAlpha(_shadowColor) > 0) { NSShadow *shadow = [[NSShadow alloc] init]; @@ -363,8 +511,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; copiedContainer.size = self.bounds.size; [copiedContainer makeImmutable]; NSMutableAttributedString *mutableText = [_attributedText mutableCopy] ?: [[NSMutableAttributedString alloc] init]; - - [self prepareAttributedString:mutableText]; + + [self prepareAttributedString:mutableText isForIntrinsicSize:NO]; return @{ @"container": copiedContainer, @@ -373,104 +521,12 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; }; } -/** - * If it can't find a compatible layout, this method creates one. - * - * NOTE: Be careful to copy `text` if needed. - */ -+ (ASTextLayout *)compatibleLayoutWithContainer:(ASTextContainer *)container - text:(NSAttributedString *)text NS_RETURNS_RETAINED - -{ - // Allocate layoutCacheLock on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) - static ASDN::StaticMutex& layoutCacheLock = *new ASDN::StaticMutex; - static NSCache *textLayoutCache; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - textLayoutCache = [[NSCache alloc] init]; - }); - - layoutCacheLock.lock(); - - ASTextCacheValue *cacheValue = [textLayoutCache objectForKey:text]; - if (cacheValue == nil) { - cacheValue = [[ASTextCacheValue alloc] init]; - [textLayoutCache setObject:cacheValue forKey:[text copy]]; - } - - // Lock the cache item for the rest of the method. Only after acquiring can we release the NSCache. - ASDN::MutexLocker lock(cacheValue->_m); - layoutCacheLock.unlock(); - - CGRect containerBounds = (CGRect){ .size = container.size }; - { - for (let &t : cacheValue->_layouts) { - CGSize constrainedSize = std::get<0>(t); - ASTextLayout *layout = std::get<1>(t); - - CGSize layoutSize = layout.textBoundingSize; - // 1. CoreText can return frames that are narrower than the constrained width, for obvious reasons. - // 2. CoreText can return frames that are slightly wider than the constrained width, for some reason. - // We have to trust that somehow it's OK to try and draw within our size constraint, despite the return value. - // 3. Thus, those two values (constrained width & returned width) form a range, where - // intermediate values in that range will be snapped. Thus, we can use a given layout as long as our - // width is in that range, between the min and max of those two values. - CGRect minRect = CGRectMake(0, 0, MIN(layoutSize.width, constrainedSize.width), MIN(layoutSize.height, constrainedSize.height)); - if (!CGRectContainsRect(containerBounds, minRect)) { - continue; - } - CGRect maxRect = CGRectMake(0, 0, MAX(layoutSize.width, constrainedSize.width), MAX(layoutSize.height, constrainedSize.height)); - if (!CGRectContainsRect(maxRect, containerBounds)) { - continue; - } - if (!CGSizeEqualToSize(container.size, constrainedSize)) { - continue; - } - - // Now check container params. - ASTextContainer *otherContainer = layout.container; - if (!UIEdgeInsetsEqualToEdgeInsets(container.insets, otherContainer.insets)) { - continue; - } - if (!ASObjectIsEqual(container.exclusionPaths, otherContainer.exclusionPaths)) { - continue; - } - if (container.maximumNumberOfRows != otherContainer.maximumNumberOfRows) { - continue; - } - if (container.truncationType != otherContainer.truncationType) { - continue; - } - if (!ASObjectIsEqual(container.truncationToken, otherContainer.truncationToken)) { - continue; - } - // TODO: When we get a cache hit, move this entry to the front (LRU). - return layout; - } - } - - // Cache Miss. Compute the text layout. - ASTextLayout *layout = [ASTextLayout layoutWithContainer:container text:text]; - - // Store the result in the cache. - { - // This is a critical section. However we also must hold the lock until this point, in case - // another thread requests this cache item while a layout is being calculated, so they don't race. - cacheValue->_layouts.push_front(std::make_tuple(container.size, layout)); - if (cacheValue->_layouts.size() > 3) { - cacheValue->_layouts.pop_back(); - } - } - - return layout; -} - + (void)drawRect:(CGRect)bounds withParameters:(NSDictionary *)layoutDict isCancelled:(NS_NOESCAPE asdisplaynode_iscancelled_block_t)isCancelledBlock isRasterizing:(BOOL)isRasterizing { ASTextContainer *container = layoutDict[@"container"]; NSAttributedString *text = layoutDict[@"text"]; UIColor *bgColor = layoutDict[@"bgColor"]; - ASTextLayout *layout = [self compatibleLayoutWithContainer:container text:text]; + ASTextLayout *layout = ASTextNodeCompatibleLayoutWithContainerAndText(container, text); if (isCancelledBlock()) { return; @@ -519,21 +575,18 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; // See discussion in https://github.com/TextureGroup/Texture/pull/396 ASTextContainer *containerCopy = [_textContainer copy]; containerCopy.size = self.calculatedSize; - ASTextLayout *layout = [ASTextNode2 compatibleLayoutWithContainer:containerCopy text:_attributedText]; - NSRange visibleRange = layout.visibleRange; - NSRange clampedRange = NSIntersectionRange(visibleRange, NSMakeRange(0, _attributedText.length)); + ASTextLayout *layout = ASTextNodeCompatibleLayoutWithContainerAndText(containerCopy, _attributedText); - ASTextRange *range = [layout closestTextRangeAtPoint:point]; - - // For now, assume that a tap inside this text, but outside the text range is a tap on the - // truncation token. - if (![layout textRangeAtPoint:point]) { + if ([self _locked_pointInsideAdditionalTruncationMessage:point withLayout:layout]) { if (inAdditionalTruncationMessageOut != NULL) { *inAdditionalTruncationMessageOut = YES; } return nil; } + NSRange visibleRange = layout.visibleRange; + NSRange clampedRange = NSIntersectionRange(visibleRange, NSMakeRange(0, _attributedText.length)); + ASTextRange *range = [layout closestTextRangeAtPoint:point]; NSRange effectiveRange = NSMakeRange(0, 0); for (__strong NSString *attributeName in self.linkAttributeNames) { id value = [self.attributedText attribute:attributeName atIndex:range.start.offset longestEffectiveRange:&effectiveRange inRange:clampedRange]; @@ -565,6 +618,61 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; return nil; } +- (BOOL)_locked_pointInsideAdditionalTruncationMessage:(CGPoint)point withLayout:(ASTextLayout *)layout +{ + // Check if the range is within the additional truncation range + BOOL inAdditionalTruncationMessage = NO; + + CTLineRef truncatedCTLine = layout.truncatedLine.CTLine; + if (truncatedCTLine != NULL && _additionalTruncationMessage != nil) { + CFIndex stringIndexForPosition = CTLineGetStringIndexForPosition(truncatedCTLine, point); + if (stringIndexForPosition != kCFNotFound) { + CFIndex truncatedCTLineGlyphCount = CTLineGetGlyphCount(truncatedCTLine); + + CTLineRef truncationTokenLine = CTLineCreateWithAttributedString((CFAttributedStringRef)_truncationAttributedText); + CFIndex truncationTokenLineGlyphCount = truncationTokenLine ? CTLineGetGlyphCount(truncationTokenLine) : 0; + + CTLineRef additionalTruncationTokenLine = CTLineCreateWithAttributedString((CFAttributedStringRef)_additionalTruncationMessage); + CFIndex additionalTruncationTokenLineGlyphCount = additionalTruncationTokenLine ? CTLineGetGlyphCount(additionalTruncationTokenLine) : 0; + + switch (_textContainer.truncationType) { + case ASTextTruncationTypeStart: { + CFIndex composedTruncationTextLineGlyphCount = truncationTokenLineGlyphCount + additionalTruncationTokenLineGlyphCount; + if (stringIndexForPosition > truncationTokenLineGlyphCount && + stringIndexForPosition < composedTruncationTextLineGlyphCount) { + inAdditionalTruncationMessage = YES; + } + break; + } + case ASTextTruncationTypeMiddle: { + CFIndex composedTruncationTextLineGlyphCount = truncationTokenLineGlyphCount + additionalTruncationTokenLineGlyphCount; + CFIndex firstTruncatedTokenIndex = (truncatedCTLineGlyphCount - composedTruncationTextLineGlyphCount) / 2.0; + if ((firstTruncatedTokenIndex + truncationTokenLineGlyphCount) < stringIndexForPosition && + stringIndexForPosition < (firstTruncatedTokenIndex + composedTruncationTextLineGlyphCount)) { + inAdditionalTruncationMessage = YES; + } + break; + } + case ASTextTruncationTypeEnd: { + if (stringIndexForPosition > (truncatedCTLineGlyphCount - additionalTruncationTokenLineGlyphCount)) { + inAdditionalTruncationMessage = YES; + } + break; + } + default: + // For now, assume that a tap inside this text, but outside the text range is a tap on the + // truncation token. + if (![layout textRangeAtPoint:point]) { + inAdditionalTruncationMessage = YES; + } + break; + } + } + } + + return inAdditionalTruncationMessage; +} + #pragma mark - UIGestureRecognizerDelegate - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer @@ -737,9 +845,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; NSUInteger lastCharIndex = NSIntegerMax; BOOL linkCrossesVisibleRange = (lastCharIndex > range.location) && (lastCharIndex < NSMaxRange(range) - 1); - if (inAdditionalTruncationMessage) { - return YES; - } else if (range.length && !linkCrossesVisibleRange && linkAttributeValue != nil && linkAttributeName != nil) { + if (range.length > 0 && !linkCrossesVisibleRange && linkAttributeValue != nil && linkAttributeName != nil) { return YES; } else { return NO; @@ -775,12 +881,12 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; // See discussion in https://github.com/TextureGroup/Texture/pull/396 ASTextContainer *containerCopy = [_textContainer copy]; containerCopy.size = self.calculatedSize; - ASTextLayout *layout = [ASTextNode2 compatibleLayoutWithContainer:containerCopy text:_attributedText]; + ASTextLayout *layout = ASTextNodeCompatibleLayoutWithContainerAndText(containerCopy, _attributedText); visibleRange = layout.visibleRange; } NSRange truncationMessageRange = [self _additionalTruncationMessageRangeWithVisibleRange:visibleRange]; [self _setHighlightRange:truncationMessageRange forAttributeName:ASTextNodeTruncationTokenAttributeName value:nil animated:YES]; - } else if (range.length && !linkCrossesVisibleRange && linkAttributeValue != nil && linkAttributeName != nil) { + } else if (range.length > 0 && !linkCrossesVisibleRange && linkAttributeValue != nil && linkAttributeName != nil) { [self _setHighlightRange:range forAttributeName:linkAttributeName value:linkAttributeValue animated:YES]; } @@ -1031,8 +1137,19 @@ static NSAttributedString *DefaultTruncationAttributedString() - (BOOL)isTruncated { - AS_TEXT_ALERT_UNIMPLEMENTED_FEATURE(); - return NO; + return ASLockedSelf([self locked_textLayoutForSize:[self _locked_threadSafeBounds].size].truncatedLine == nil); +} + +- (BOOL)shouldTruncateForConstrainedSize:(ASSizeRange)constrainedSize +{ + return ASLockedSelf([self locked_textLayoutForSize:constrainedSize.max].truncatedLine != nil); +} + +- (ASTextLayout *)locked_textLayoutForSize:(CGSize)size +{ + ASTextContainer *container = [_textContainer copy]; + container.size = size; + return ASTextNodeCompatibleLayoutWithContainerAndText(container, _attributedText); } - (NSUInteger)maximumNumberOfLines @@ -1061,10 +1178,15 @@ static NSAttributedString *DefaultTruncationAttributedString() - (void)_invalidateTruncationText { ASLockScopeSelf(); - _textContainer.truncationToken = nil; + [self _locked_invalidateTruncationText]; [self setNeedsDisplay]; } +- (void)_locked_invalidateTruncationText +{ + _textContainer.truncationToken = nil; +} + /** * @return the additional truncation message range within the as-rendered text. * Must be called from main thread diff --git a/Source/ASTextNodeCommon.h b/Source/ASTextNodeCommon.h index c702561e63..fbb32ca39e 100644 --- a/Source/ASTextNodeCommon.h +++ b/Source/ASTextNodeCommon.h @@ -10,6 +10,13 @@ @class ASTextNode; +#define AS_TEXT_ALERT_UNIMPLEMENTED_FEATURE() { \ + static dispatch_once_t onceToken; \ + dispatch_once(&onceToken, ^{ \ + NSLog(@"[Texture] Warning: Feature %@ is unimplemented in %@.", NSStringFromSelector(_cmd), NSStringFromClass(self.class)); \ + });\ +} + /** * Highlight styles. */ diff --git a/Source/ASVideoNode.mm b/Source/ASVideoNode.mm index de3ec563a4..8455b362cd 100644 --- a/Source/ASVideoNode.mm +++ b/Source/ASVideoNode.mm @@ -10,6 +10,7 @@ #import #import #import +#import #import #import #import @@ -322,7 +323,7 @@ static NSString * const kRate = @"rate"; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - ASLockScopeSelf(); + ASDN::UniqueLock l(__instanceLock__); if (object == _currentPlayerItem) { if ([keyPath isEqualToString:kStatus]) { @@ -330,8 +331,9 @@ static NSString * const kRate = @"rate"; if (self.playerState != ASVideoNodePlayerStatePlaying) { self.playerState = ASVideoNodePlayerStateReadyToPlay; if (_shouldBePlaying && ASInterfaceStateIncludesVisible(self.interfaceState)) { - ASUnlockScope(self); + l.unlock(); [self play]; + l.lock(); } } // If we don't yet have a placeholder image update it now that we should have data available for it @@ -354,8 +356,10 @@ static NSString * const kRate = @"rate"; [self.delegate videoNodeDidRecoverFromStall:self]; } - ASUnlockScope(self); + l.unlock(); [self play]; // autoresume after buffer catches up + // NOTE: Early return without re-locking. + return; } } else if ([keyPath isEqualToString:kplaybackBufferEmpty]) { if (_shouldBePlaying && [change[NSKeyValueChangeNewKey] boolValue] == YES && ASInterfaceStateIncludesVisible(self.interfaceState)) { @@ -373,6 +377,8 @@ static NSString * const kRate = @"rate"; } } } + + // NOTE: Early return above. } - (void)tapped diff --git a/Source/ASVisibilityProtocols.m b/Source/ASVisibilityProtocols.mm similarity index 95% rename from Source/ASVisibilityProtocols.m rename to Source/ASVisibilityProtocols.mm index 9ee52c433f..b13a683bea 100644 --- a/Source/ASVisibilityProtocols.m +++ b/Source/ASVisibilityProtocols.mm @@ -1,5 +1,5 @@ // -// ASVisibilityProtocols.m +// ASVisibilityProtocols.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/AsyncDisplayKit+IGListKitMethods.m b/Source/AsyncDisplayKit+IGListKitMethods.mm similarity index 100% rename from Source/AsyncDisplayKit+IGListKitMethods.m rename to Source/AsyncDisplayKit+IGListKitMethods.mm diff --git a/Source/Base/ASAssert.h b/Source/Base/ASAssert.h index e838c86dd1..f00ce967d6 100644 --- a/Source/Base/ASAssert.h +++ b/Source/Base/ASAssert.h @@ -63,6 +63,7 @@ #define ASDisplayNodeCAssertPositiveReal(description, num) ASDisplayNodeCAssert(num >= 0 && num <= CGFLOAT_MAX, @"%@ must be a real positive integer: %f.", description, (CGFloat)num) #define ASDisplayNodeCAssertInfOrPositiveReal(description, num) ASDisplayNodeCAssert(isinf(num) || (num >= 0 && num <= CGFLOAT_MAX), @"%@ must be infinite or a real positive integer: %f.", description, (CGFloat)num) +#define ASDisplayNodeCAssertPermanent(object) ASDisplayNodeCAssert(CFGetRetainCount((__bridge CFTypeRef)(object)) == CFGetRetainCount(kCFNull), @"Expected %s to be a permanent object.", #object) #define ASDisplayNodeErrorDomain @"ASDisplayNodeErrorDomain" #define ASDisplayNodeNonFatalErrorCode 1 diff --git a/Source/Base/ASAssert.m b/Source/Base/ASAssert.mm similarity index 82% rename from Source/Base/ASAssert.m rename to Source/Base/ASAssert.mm index 73bee34ea9..0e2fc9902c 100644 --- a/Source/Base/ASAssert.m +++ b/Source/Base/ASAssert.mm @@ -1,5 +1,5 @@ // -// ASAssert.m +// ASAssert.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. @@ -39,19 +39,19 @@ static pthread_key_t ASMainThreadAssertionsDisabledKey() { } BOOL ASMainThreadAssertionsAreDisabled() { - return (pthread_getspecific(ASMainThreadAssertionsDisabledKey()) > 0); + return (nullptr != pthread_getspecific(ASMainThreadAssertionsDisabledKey())); } void ASPushMainThreadAssertionsDisabled() { let key = ASMainThreadAssertionsDisabledKey(); - let oldVal = pthread_getspecific(key); - pthread_setspecific(key, oldVal + 1); + let oldVal = (intptr_t)pthread_getspecific(key); + pthread_setspecific(key, (void *)(oldVal + 1)); } void ASPopMainThreadAssertionsDisabled() { let key = ASMainThreadAssertionsDisabledKey(); - let oldVal = pthread_getspecific(key); - pthread_setspecific(key, oldVal - 1); + let oldVal = (intptr_t)pthread_getspecific(key); + pthread_setspecific(key, (void *)(oldVal - 1)); ASDisplayNodeCAssert(oldVal > 0, @"Attempt to pop thread assertion-disabling without corresponding push."); } diff --git a/Source/Base/ASAvailability.h b/Source/Base/ASAvailability.h index 2cc7400018..312fe330b9 100644 --- a/Source/Base/ASAvailability.h +++ b/Source/Base/ASAvailability.h @@ -14,15 +14,15 @@ #define AS_TLS_AVAILABLE 0 #ifndef AS_USE_PHOTOS -# define AS_USE_PHOTOS 0 + #define AS_USE_PHOTOS 0 #endif #ifndef AS_USE_MAPKIT -# define AS_USE_MAPKIT 0 + #define AS_USE_MAPKIT 0 #endif #ifndef AS_USE_ASSETS_LIBRARY -# define AS_USE_ASSETS_LIBRARY 0 + #define AS_USE_ASSETS_LIBRARY 0 #endif #ifndef kCFCoreFoundationVersionNumber_iOS_10_0 diff --git a/Source/Base/ASBaseDefines.h b/Source/Base/ASBaseDefines.h index 959e15d839..65335e275e 100644 --- a/Source/Base/ASBaseDefines.h +++ b/Source/Base/ASBaseDefines.h @@ -12,6 +12,7 @@ #define AS_EXTERN FOUNDATION_EXTERN #define unowned __unsafe_unretained +// TODO: Remove these now that we're all-C++. #if defined(__cplusplus) # define var auto # define let const auto @@ -20,6 +21,18 @@ # define let const __auto_type #endif +/** + * Hack to support building for iOS with Xcode 9. UIUserInterfaceStyle was previously tvOS-only, + * and it was added to iOS 12. Xcode 9 (iOS 11 SDK) will flat-out refuse to build anything that + * references this enum targeting iOS, even if it's guarded with the right availability macros, + * because it thinks the entire platform isn't compatible with the enum. + */ +#if TARGET_OS_TV || (defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_12_0) +#define AS_BUILD_UIUSERINTERFACESTYLE 1 +#else +#define AS_BUILD_UIUSERINTERFACESTYLE 0 +#endif + #ifdef __GNUC__ # define ASDISPLAYNODE_GNUC(major, minor) \ (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) diff --git a/Source/Base/ASDisplayNode+Ancestry.m b/Source/Base/ASDisplayNode+Ancestry.mm similarity index 98% rename from Source/Base/ASDisplayNode+Ancestry.m rename to Source/Base/ASDisplayNode+Ancestry.mm index 33b53b18fc..7003064c70 100644 --- a/Source/Base/ASDisplayNode+Ancestry.m +++ b/Source/Base/ASDisplayNode+Ancestry.mm @@ -1,5 +1,5 @@ // -// ASDisplayNode+Ancestry.m +// ASDisplayNode+Ancestry.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Base/ASLog.m b/Source/Base/ASLog.mm similarity index 99% rename from Source/Base/ASLog.m rename to Source/Base/ASLog.mm index 8dcd8a8f34..270246454b 100644 --- a/Source/Base/ASLog.m +++ b/Source/Base/ASLog.mm @@ -1,5 +1,5 @@ // -// ASLog.m +// ASLog.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Debug/AsyncDisplayKit+Debug.m b/Source/Debug/AsyncDisplayKit+Debug.mm similarity index 99% rename from Source/Debug/AsyncDisplayKit+Debug.m rename to Source/Debug/AsyncDisplayKit+Debug.mm index 558439f904..f527098dcc 100644 --- a/Source/Debug/AsyncDisplayKit+Debug.m +++ b/Source/Debug/AsyncDisplayKit+Debug.mm @@ -1,5 +1,5 @@ // -// AsyncDisplayKit+Debug.m +// AsyncDisplayKit+Debug.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Debug/AsyncDisplayKit+Tips.m b/Source/Debug/AsyncDisplayKit+Tips.mm similarity index 93% rename from Source/Debug/AsyncDisplayKit+Tips.m rename to Source/Debug/AsyncDisplayKit+Tips.mm index 19a955b68c..f1a3ec8d72 100644 --- a/Source/Debug/AsyncDisplayKit+Tips.m +++ b/Source/Debug/AsyncDisplayKit+Tips.mm @@ -1,5 +1,5 @@ // -// AsyncDisplayKit+Tips.m +// AsyncDisplayKit+Tips.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import "AsyncDisplayKit+Tips.h" +#import #import @implementation ASDisplayNode (Tips) diff --git a/Source/Details/ASAbstractLayoutController.mm b/Source/Details/ASAbstractLayoutController.mm index f63a3ca86c..b8947ae49b 100644 --- a/Source/Details/ASAbstractLayoutController.mm +++ b/Source/Details/ASAbstractLayoutController.mm @@ -8,11 +8,9 @@ // #import - +#import #import -#include - ASRangeTuningParameters const ASRangeTuningParametersZero = {}; BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRangeTuningParameters lhs, ASRangeTuningParameters rhs) @@ -89,6 +87,52 @@ CGRect CGRectExpandToRangeWithScrollableDirections(CGRect rect, ASRangeTuningPar @implementation ASAbstractLayoutController ++ (std::vector>)defaultTuningParameters +{ + var tuningParameters = std::vector> (ASLayoutRangeModeCount, std::vector (ASLayoutRangeTypeCount)); + + tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypeDisplay] = { + .leadingBufferScreenfuls = 1.0, + .trailingBufferScreenfuls = 0.5 + }; + + tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypePreload] = { + .leadingBufferScreenfuls = 2.5, + .trailingBufferScreenfuls = 1.5 + }; + + tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypeDisplay] = { + .leadingBufferScreenfuls = 0.25, + .trailingBufferScreenfuls = 0.25 + }; + tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypePreload] = { + .leadingBufferScreenfuls = 0.5, + .trailingBufferScreenfuls = 0.25 + }; + + tuningParameters[ASLayoutRangeModeVisibleOnly][ASLayoutRangeTypeDisplay] = { + .leadingBufferScreenfuls = 0, + .trailingBufferScreenfuls = 0 + }; + tuningParameters[ASLayoutRangeModeVisibleOnly][ASLayoutRangeTypePreload] = { + .leadingBufferScreenfuls = 0, + .trailingBufferScreenfuls = 0 + }; + + // The Low Memory range mode has special handling. Because a zero range still includes the visible area / bounds, + // in order to implement the behavior of releasing all graphics memory (backing stores), ASRangeController must check + // for this range mode and use an empty set for displayIndexPaths rather than querying the ASLayoutController for the indexPaths. + tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypeDisplay] = { + .leadingBufferScreenfuls = 0, + .trailingBufferScreenfuls = 0 + }; + tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypePreload] = { + .leadingBufferScreenfuls = 0, + .trailingBufferScreenfuls = 0 + }; + return tuningParameters; +} + - (instancetype)init { if (!(self = [super init])) { @@ -96,46 +140,7 @@ CGRect CGRectExpandToRangeWithScrollableDirections(CGRect rect, ASRangeTuningPar } ASDisplayNodeAssert(self.class != [ASAbstractLayoutController class], @"Should never create instances of abstract class ASAbstractLayoutController."); - _tuningParameters = std::vector> (ASLayoutRangeModeCount, std::vector (ASLayoutRangeTypeCount)); - - _tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypeDisplay] = { - .leadingBufferScreenfuls = 1.0, - .trailingBufferScreenfuls = 0.5 - }; - _tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypePreload] = { - .leadingBufferScreenfuls = 2.5, - .trailingBufferScreenfuls = 1.5 - }; - - _tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypeDisplay] = { - .leadingBufferScreenfuls = 0.25, - .trailingBufferScreenfuls = 0.25 - }; - _tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypePreload] = { - .leadingBufferScreenfuls = 0.5, - .trailingBufferScreenfuls = 0.25 - }; - - _tuningParameters[ASLayoutRangeModeVisibleOnly][ASLayoutRangeTypeDisplay] = { - .leadingBufferScreenfuls = 0, - .trailingBufferScreenfuls = 0 - }; - _tuningParameters[ASLayoutRangeModeVisibleOnly][ASLayoutRangeTypePreload] = { - .leadingBufferScreenfuls = 0, - .trailingBufferScreenfuls = 0 - }; - - // The Low Memory range mode has special handling. Because a zero range still includes the visible area / bounds, - // in order to implement the behavior of releasing all graphics memory (backing stores), ASRangeController must check - // for this range mode and use an empty set for displayIndexPaths rather than querying the ASLayoutController for the indexPaths. - _tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypeDisplay] = { - .leadingBufferScreenfuls = 0, - .trailingBufferScreenfuls = 0 - }; - _tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypePreload] = { - .leadingBufferScreenfuls = 0, - .trailingBufferScreenfuls = 0 - }; + _tuningParameters = [[self class] defaultTuningParameters]; return self; } diff --git a/Source/Details/ASBasicImageDownloader.mm b/Source/Details/ASBasicImageDownloader.mm index 156d7f9512..b6629b5cb6 100644 --- a/Source/Details/ASBasicImageDownloader.mm +++ b/Source/Details/ASBasicImageDownloader.mm @@ -39,11 +39,11 @@ NSString * const kASBasicImageDownloaderContextCompletionBlock = @"kASBasicImage static NSMutableDictionary *currentRequests = nil; // Allocate currentRequestsLock on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) -static ASDN::StaticMutex& currentRequestsLock = *new ASDN::StaticMutex; +static auto *currentRequestsLock = new ASDN::Mutex; + (ASBasicImageDownloaderContext *)contextForURL:(NSURL *)URL { - ASDN::StaticMutexLocker l(currentRequestsLock); + ASDN::MutexLocker l(*currentRequestsLock); if (!currentRequests) { currentRequests = [[NSMutableDictionary alloc] init]; } @@ -57,7 +57,7 @@ static ASDN::StaticMutex& currentRequestsLock = *new ASDN::StaticMutex; + (void)cancelContextWithURL:(NSURL *)URL { - ASDN::StaticMutexLocker l(currentRequestsLock); + ASDN::MutexLocker l(*currentRequestsLock); if (currentRequests) { [currentRequests removeObjectForKey:URL]; } diff --git a/Source/Details/ASBatchContext.m b/Source/Details/ASBatchContext.mm similarity index 98% rename from Source/Details/ASBatchContext.m rename to Source/Details/ASBatchContext.mm index 9dbaff0a4f..ee4ec173a5 100644 --- a/Source/Details/ASBatchContext.m +++ b/Source/Details/ASBatchContext.mm @@ -1,5 +1,5 @@ // -// ASBatchContext.m +// ASBatchContext.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASCollectionFlowLayoutDelegate.m b/Source/Details/ASCollectionFlowLayoutDelegate.mm similarity index 98% rename from Source/Details/ASCollectionFlowLayoutDelegate.m rename to Source/Details/ASCollectionFlowLayoutDelegate.mm index 3e3bbb5e44..37d311d24e 100644 --- a/Source/Details/ASCollectionFlowLayoutDelegate.m +++ b/Source/Details/ASCollectionFlowLayoutDelegate.mm @@ -1,5 +1,5 @@ // -// ASCollectionFlowLayoutDelegate.m +// ASCollectionFlowLayoutDelegate.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASCollectionLayoutContext.m b/Source/Details/ASCollectionLayoutContext.mm similarity index 98% rename from Source/Details/ASCollectionLayoutContext.m rename to Source/Details/ASCollectionLayoutContext.mm index 4596f20b87..5f82fd76fa 100644 --- a/Source/Details/ASCollectionLayoutContext.m +++ b/Source/Details/ASCollectionLayoutContext.mm @@ -1,5 +1,5 @@ // -// ASCollectionLayoutContext.m +// ASCollectionLayoutContext.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Details/ASCollectionViewLayoutController.m b/Source/Details/ASCollectionViewLayoutController.m deleted file mode 100644 index 100efce21a..0000000000 --- a/Source/Details/ASCollectionViewLayoutController.m +++ /dev/null @@ -1,131 +0,0 @@ -// -// ASCollectionViewLayoutController.m -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK -#import - -#import -#import -#import -#import -#import - -struct ASRangeGeometry { - CGRect rangeBounds; - CGRect updateBounds; -}; -typedef struct ASRangeGeometry ASRangeGeometry; - - -#pragma mark - -#pragma mark ASCollectionViewLayoutController - -@interface ASCollectionViewLayoutController () -{ - @package - ASCollectionView * __weak _collectionView; - UICollectionViewLayout * __strong _collectionViewLayout; -} -@end - -@implementation ASCollectionViewLayoutController - -- (instancetype)initWithCollectionView:(ASCollectionView *)collectionView -{ - if (!(self = [super init])) { - return nil; - } - - _collectionView = collectionView; - _collectionViewLayout = [collectionView collectionViewLayout]; - return self; -} - -- (NSHashTable *)elementsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType map:(ASElementMap *)map -{ - ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeMode:rangeMode rangeType:rangeType]; - CGRect rangeBounds = [self rangeBoundsWithScrollDirection:scrollDirection rangeTuningParameters:tuningParameters]; - return [self elementsWithinRangeBounds:rangeBounds map:map]; -} - -- (void)allElementsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode displaySet:(NSHashTable *__autoreleasing _Nullable *)displaySet preloadSet:(NSHashTable *__autoreleasing _Nullable *)preloadSet map:(ASElementMap *)map -{ - if (displaySet == NULL || preloadSet == NULL) { - return; - } - - ASRangeTuningParameters displayParams = [self tuningParametersForRangeMode:rangeMode rangeType:ASLayoutRangeTypeDisplay]; - ASRangeTuningParameters preloadParams = [self tuningParametersForRangeMode:rangeMode rangeType:ASLayoutRangeTypePreload]; - CGRect displayBounds = [self rangeBoundsWithScrollDirection:scrollDirection rangeTuningParameters:displayParams]; - CGRect preloadBounds = [self rangeBoundsWithScrollDirection:scrollDirection rangeTuningParameters:preloadParams]; - - CGRect unionBounds = CGRectUnion(displayBounds, preloadBounds); - NSArray *layoutAttributes = [_collectionViewLayout layoutAttributesForElementsInRect:unionBounds]; - NSInteger count = layoutAttributes.count; - - __auto_type display = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality capacity:count]; - __auto_type preload = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality capacity:count]; - - for (UICollectionViewLayoutAttributes *la in layoutAttributes) { - // Manually filter out elements that don't intersect the range bounds. - // See comment in elementsForItemsWithinRangeBounds: - // This is re-implemented here so that the iteration over layoutAttributes can be done once to check both ranges. - CGRect frame = la.frame; - BOOL intersectsDisplay = CGRectIntersectsRect(displayBounds, frame); - BOOL intersectsPreload = CGRectIntersectsRect(preloadBounds, frame); - if (intersectsDisplay == NO && intersectsPreload == NO && CATransform3DIsIdentity(la.transform3D) == YES) { - // Questionable why the element would be included here, but it doesn't belong. - continue; - } - - // Avoid excessive retains and releases, as well as property calls. We know the element is kept alive by map. - __unsafe_unretained ASCollectionElement *e = [map elementForLayoutAttributes:la]; - if (e != nil && intersectsDisplay) { - [display addObject:e]; - } - if (e != nil && intersectsPreload) { - [preload addObject:e]; - } - } - - *displaySet = display; - *preloadSet = preload; - return; -} - -- (NSHashTable *)elementsWithinRangeBounds:(CGRect)rangeBounds map:(ASElementMap *)map -{ - NSArray *layoutAttributes = [_collectionViewLayout layoutAttributesForElementsInRect:rangeBounds]; - NSHashTable *elementSet = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality capacity:layoutAttributes.count]; - - for (UICollectionViewLayoutAttributes *la in layoutAttributes) { - // Manually filter out elements that don't intersect the range bounds. - // If a layout returns elements outside the requested rect this can be a huge problem. - // For instance in a paging flow, you may only want to preload 3 pages (one center, one on each side) - // but if flow layout includes the 4th page (which it does! as of iOS 9&10), you will preload a 4th - // page as well. - if (CATransform3DIsIdentity(la.transform3D) && CGRectIntersectsRect(la.frame, rangeBounds) == NO) { - continue; - } - [elementSet addObject:[map elementForLayoutAttributes:la]]; - } - - return elementSet; -} - -- (CGRect)rangeBoundsWithScrollDirection:(ASScrollDirection)scrollDirection - rangeTuningParameters:(ASRangeTuningParameters)tuningParameters -{ - CGRect rect = _collectionView.bounds; - - return CGRectExpandToRangeWithScrollableDirections(rect, tuningParameters, [_collectionView scrollableDirections], scrollDirection); -} - -@end -#endif diff --git a/Source/Details/ASCollectionViewLayoutController.mm b/Source/Details/ASCollectionViewLayoutController.mm index fe521175b6..1d7f1ca013 100644 --- a/Source/Details/ASCollectionViewLayoutController.mm +++ b/Source/Details/ASCollectionViewLayoutController.mm @@ -1,17 +1,18 @@ // // ASCollectionViewLayoutController.mm -// AsyncDisplayKit +// Texture // -// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // + #ifndef MINIMAL_ASDK #import #import -#import +#import +#import #import #import @@ -21,7 +22,6 @@ struct ASRangeGeometry { }; typedef struct ASRangeGeometry ASRangeGeometry; - #pragma mark - #pragma mark ASCollectionViewLayoutController @@ -46,21 +46,64 @@ typedef struct ASRangeGeometry ASRangeGeometry; return self; } -- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType +- (NSHashTable *)elementsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType map:(ASElementMap *)map { ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeMode:rangeMode rangeType:rangeType]; CGRect rangeBounds = [self rangeBoundsWithScrollDirection:scrollDirection rangeTuningParameters:tuningParameters]; - return [self indexPathsForItemsWithinRangeBounds:rangeBounds]; + return [self elementsWithinRangeBounds:rangeBounds map:map]; } -- (NSSet *)indexPathsForItemsWithinRangeBounds:(CGRect)rangeBounds +- (void)allElementsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode displaySet:(NSHashTable *__autoreleasing _Nullable *)displaySet preloadSet:(NSHashTable *__autoreleasing _Nullable *)preloadSet map:(ASElementMap *)map +{ + if (displaySet == NULL || preloadSet == NULL) { + return; + } + + ASRangeTuningParameters displayParams = [self tuningParametersForRangeMode:rangeMode rangeType:ASLayoutRangeTypeDisplay]; + ASRangeTuningParameters preloadParams = [self tuningParametersForRangeMode:rangeMode rangeType:ASLayoutRangeTypePreload]; + CGRect displayBounds = [self rangeBoundsWithScrollDirection:scrollDirection rangeTuningParameters:displayParams]; + CGRect preloadBounds = [self rangeBoundsWithScrollDirection:scrollDirection rangeTuningParameters:preloadParams]; + + CGRect unionBounds = CGRectUnion(displayBounds, preloadBounds); + NSArray *layoutAttributes = [_collectionViewLayout layoutAttributesForElementsInRect:unionBounds]; + NSInteger count = layoutAttributes.count; + + __auto_type display = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality capacity:count]; + __auto_type preload = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality capacity:count]; + + for (UICollectionViewLayoutAttributes *la in layoutAttributes) { + // Manually filter out elements that don't intersect the range bounds. + // See comment in elementsForItemsWithinRangeBounds: + // This is re-implemented here so that the iteration over layoutAttributes can be done once to check both ranges. + CGRect frame = la.frame; + BOOL intersectsDisplay = CGRectIntersectsRect(displayBounds, frame); + BOOL intersectsPreload = CGRectIntersectsRect(preloadBounds, frame); + if (intersectsDisplay == NO && intersectsPreload == NO && CATransform3DIsIdentity(la.transform3D) == YES) { + // Questionable why the element would be included here, but it doesn't belong. + continue; + } + + // Avoid excessive retains and releases, as well as property calls. We know the element is kept alive by map. + __unsafe_unretained ASCollectionElement *e = [map elementForLayoutAttributes:la]; + if (e != nil && intersectsDisplay) { + [display addObject:e]; + } + if (e != nil && intersectsPreload) { + [preload addObject:e]; + } + } + + *displaySet = display; + *preloadSet = preload; + return; +} + +- (NSHashTable *)elementsWithinRangeBounds:(CGRect)rangeBounds map:(ASElementMap *)map { NSArray *layoutAttributes = [_collectionViewLayout layoutAttributesForElementsInRect:rangeBounds]; - NSMutableSet *indexPathSet = [NSMutableSet setWithCapacity:layoutAttributes.count]; + NSHashTable *elementSet = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality capacity:layoutAttributes.count]; for (UICollectionViewLayoutAttributes *la in layoutAttributes) { - //ASDisplayNodeAssert(![indexPathSet containsObject:la.indexPath], @"Shouldn't already contain indexPath"); - // Manually filter out elements that don't intersect the range bounds. // If a layout returns elements outside the requested rect this can be a huge problem. // For instance in a paging flow, you may only want to preload 3 pages (one center, one on each side) @@ -69,10 +112,10 @@ typedef struct ASRangeGeometry ASRangeGeometry; if (CATransform3DIsIdentity(la.transform3D) && CGRectIntersectsRect(la.frame, rangeBounds) == NO) { continue; } - [indexPathSet addObject:la.indexPath]; + [elementSet addObject:[map elementForLayoutAttributes:la]]; } - return indexPathSet; + return elementSet; } - (CGRect)rangeBoundsWithScrollDirection:(ASScrollDirection)scrollDirection @@ -84,5 +127,4 @@ typedef struct ASRangeGeometry ASRangeGeometry; } @end - #endif diff --git a/Source/Details/ASCollectionViewLayoutInspector.m b/Source/Details/ASCollectionViewLayoutInspector.mm similarity index 98% rename from Source/Details/ASCollectionViewLayoutInspector.m rename to Source/Details/ASCollectionViewLayoutInspector.mm index 22deff0f75..f02fe1c171 100644 --- a/Source/Details/ASCollectionViewLayoutInspector.m +++ b/Source/Details/ASCollectionViewLayoutInspector.mm @@ -1,5 +1,5 @@ // -// ASCollectionViewLayoutInspector.m +// ASCollectionViewLayoutInspector.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASDelegateProxy.m b/Source/Details/ASDelegateProxy.mm similarity index 99% rename from Source/Details/ASDelegateProxy.m rename to Source/Details/ASDelegateProxy.mm index ba60c23b6b..bc51bb3e36 100644 --- a/Source/Details/ASDelegateProxy.m +++ b/Source/Details/ASDelegateProxy.mm @@ -1,5 +1,5 @@ // -// ASDelegateProxy.m +// ASDelegateProxy.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASElementMap.m b/Source/Details/ASElementMap.mm similarity index 99% rename from Source/Details/ASElementMap.m rename to Source/Details/ASElementMap.mm index 721ce3db29..6df89ff6cd 100644 --- a/Source/Details/ASElementMap.m +++ b/Source/Details/ASElementMap.mm @@ -1,5 +1,5 @@ // -// ASElementMap.m +// ASElementMap.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -9,7 +9,7 @@ #ifndef MINIMAL_ASDK -#import "ASElementMap.h" +#import #import #import #import diff --git a/Source/Details/ASGraphicsContext.m b/Source/Details/ASGraphicsContext.mm similarity index 99% rename from Source/Details/ASGraphicsContext.m rename to Source/Details/ASGraphicsContext.mm index 26255a58ae..b950613d0d 100644 --- a/Source/Details/ASGraphicsContext.m +++ b/Source/Details/ASGraphicsContext.mm @@ -1,12 +1,12 @@ // -// ASGraphicsContext.m +// ASGraphicsContext.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import "ASGraphicsContext.h" +#import #import #import #import diff --git a/Source/Details/ASHashing.m b/Source/Details/ASHashing.mm similarity index 98% rename from Source/Details/ASHashing.m rename to Source/Details/ASHashing.mm index 2863e2dc58..17bf66bd82 100644 --- a/Source/Details/ASHashing.m +++ b/Source/Details/ASHashing.mm @@ -1,5 +1,5 @@ // -// ASHashing.m +// ASHashing.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Details/ASImageContainerProtocolCategories.m b/Source/Details/ASImageContainerProtocolCategories.mm similarity index 93% rename from Source/Details/ASImageContainerProtocolCategories.m rename to Source/Details/ASImageContainerProtocolCategories.mm index 1df6a9111f..c9316c32ab 100644 --- a/Source/Details/ASImageContainerProtocolCategories.m +++ b/Source/Details/ASImageContainerProtocolCategories.mm @@ -1,5 +1,5 @@ // -// ASImageContainerProtocolCategories.m +// ASImageContainerProtocolCategories.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASMainSerialQueue.mm b/Source/Details/ASMainSerialQueue.mm index 6a9baee50c..3a5fa00f85 100644 --- a/Source/Details/ASMainSerialQueue.mm +++ b/Source/Details/ASMainSerialQueue.mm @@ -40,29 +40,32 @@ - (void)performBlockOnMainThread:(dispatch_block_t)block { - ASDN::MutexLocker l(_serialQueueLock); + + ASDN::UniqueLock l(_serialQueueLock); [_blocks addObject:block]; { - ASDN::MutexUnlocker u(_serialQueueLock); + l.unlock(); [self runBlocks]; + l.lock(); } } - (void)runBlocks { dispatch_block_t mainThread = ^{ + ASDN::UniqueLock l(self->_serialQueueLock); do { - ASDN::MutexLocker l(_serialQueueLock); dispatch_block_t block; - if (_blocks.count > 0) { + if (self->_blocks.count > 0) { block = _blocks[0]; - [_blocks removeObjectAtIndex:0]; + [self->_blocks removeObjectAtIndex:0]; } else { break; } { - ASDN::MutexUnlocker u(_serialQueueLock); + l.unlock(); block(); + l.lock(); } } while (true); }; diff --git a/Source/Details/ASMutableAttributedStringBuilder.m b/Source/Details/ASMutableAttributedStringBuilder.mm similarity index 99% rename from Source/Details/ASMutableAttributedStringBuilder.m rename to Source/Details/ASMutableAttributedStringBuilder.mm index 65a2333711..b393fe1118 100644 --- a/Source/Details/ASMutableAttributedStringBuilder.m +++ b/Source/Details/ASMutableAttributedStringBuilder.mm @@ -1,5 +1,5 @@ // -// ASMutableAttributedStringBuilder.m +// ASMutableAttributedStringBuilder.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASObjectDescriptionHelpers.m b/Source/Details/ASObjectDescriptionHelpers.mm similarity index 99% rename from Source/Details/ASObjectDescriptionHelpers.m rename to Source/Details/ASObjectDescriptionHelpers.mm index db69a7bf1b..cbd6be0963 100644 --- a/Source/Details/ASObjectDescriptionHelpers.m +++ b/Source/Details/ASObjectDescriptionHelpers.mm @@ -1,5 +1,5 @@ // -// ASObjectDescriptionHelpers.m +// ASObjectDescriptionHelpers.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASPINRemoteImageDownloader.h b/Source/Details/ASPINRemoteImageDownloader.h index 898e2501b3..dceca079e2 100644 --- a/Source/Details/ASPINRemoteImageDownloader.h +++ b/Source/Details/ASPINRemoteImageDownloader.h @@ -18,6 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @class PINRemoteImageManager; +@protocol PINRemoteImageCaching; @interface ASPINRemoteImageDownloader : NSObject @@ -30,7 +31,6 @@ NS_ASSUME_NONNULL_BEGIN */ + (ASPINRemoteImageDownloader *)sharedDownloader NS_RETURNS_RETAINED; - /** * Sets the default NSURLSessionConfiguration that will be used by @c ASNetworkImageNodes and @c ASMultiplexImageNodes * while loading images off the network. This must be specified early in the application lifecycle before @@ -41,15 +41,27 @@ NS_ASSUME_NONNULL_BEGIN */ + (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration; +/** + * Sets the default NSURLSessionConfiguration that will be used by @c ASNetworkImageNodes and @c ASMultiplexImageNodes + * while loading images off the network. This must be specified early in the application lifecycle before + * `sharedDownloader` is accessed. + * + * @param configuration The session configuration that will be used by `sharedDownloader` + * @param imageCache The cache to be used by PINRemoteImage - nil will set up a default cache: PINCache + * if it is available, PINRemoteImageBasicCache (NSCache) if not. + * + */ ++ (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration + imageCache:(nullable id)imageCache; + /** * Sets a custom preconfigured PINRemoteImageManager that will be used by @c ASNetworkImageNodes and @c ASMultiplexImageNodes * while loading images off the network. This must be specified early in the application lifecycle before - * `sharedDownloader` is accessed. If nil is passed in as the PINRemoteImageManager, it will create - * a default image manager with a nil session configuration. + * `sharedDownloader` is accessed. * * @param preconfiguredPINRemoteImageManager The preconfigured remote image manager that will be used by `sharedDownloader` */ -+ (void)setSharedPreconfiguredRemoteImageManager:(nullable PINRemoteImageManager *)preconfiguredPINRemoteImageManager; ++ (void)setSharedPreconfiguredRemoteImageManager:(PINRemoteImageManager *)preconfiguredPINRemoteImageManager; /** * The shared instance of a @c PINRemoteImageManager used by all @c ASPINRemoteImageDownloaders diff --git a/Source/Details/ASPINRemoteImageDownloader.m b/Source/Details/ASPINRemoteImageDownloader.mm similarity index 80% rename from Source/Details/ASPINRemoteImageDownloader.m rename to Source/Details/ASPINRemoteImageDownloader.mm index a73d889aaa..40d2c346f7 100644 --- a/Source/Details/ASPINRemoteImageDownloader.m +++ b/Source/Details/ASPINRemoteImageDownloader.mm @@ -1,5 +1,5 @@ // -// ASPINRemoteImageDownloader.m +// ASPINRemoteImageDownloader.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -77,7 +77,7 @@ @implementation ASPINRemoteImageManager //Share image cache with sharedImageManager image cache. -- (id )defaultImageCache ++ (id )defaultImageCache { static dispatch_once_t onceToken; static id cache = nil; @@ -108,7 +108,6 @@ static PINRemoteImageManager *sharedPINRemoteImageManager = nil; + (ASPINRemoteImageDownloader *)sharedDownloader NS_RETURNS_RETAINED { - static dispatch_once_t onceToken = 0; dispatch_once(&onceToken, ^{ sharedDownloader = [[ASPINRemoteImageDownloader alloc] init]; @@ -118,56 +117,68 @@ static PINRemoteImageManager *sharedPINRemoteImageManager = nil; + (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration { - NSAssert(sharedDownloader == nil, @"Singleton has been created and session can no longer be configured."); - NSAssert1(sharedPINRemoteImageManager == nil, @"An instance of %@ has been set. Either configuration or preconfigured image manager can be set at a time and only once.", [[sharedPINRemoteImageManager class] description]); - __unused PINRemoteImageManager *sharedManager = [self sharedPINRemoteImageManagerWithConfiguration:configuration preconfiguredPINRemoteImageManager:nil]; + PINRemoteImageManager *sharedManager = [self PINRemoteImageManagerWithConfiguration:configuration imageCache:nil]; + [self setSharedPreconfiguredRemoteImageManager:sharedManager]; } -+ (void)setSharedPreconfiguredRemoteImageManager:(nullable PINRemoteImageManager *)preconfiguredPINRemoteImageManager ++ (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration + imageCache:(nullable id)imageCache { - NSAssert(sharedDownloader == nil, @"Singleton has been created and session can no longer be configured."); - NSAssert1(sharedPINRemoteImageManager == nil, @"An instance of %@ has been set. Either configuration or preconfigured image manager can be set at a time and only once.", [[sharedPINRemoteImageManager class] description]); - __unused PINRemoteImageManager *sharedManager = [self sharedPINRemoteImageManagerWithConfiguration:nil preconfiguredPINRemoteImageManager:preconfiguredPINRemoteImageManager]; + PINRemoteImageManager *sharedManager = [self PINRemoteImageManagerWithConfiguration:configuration imageCache:imageCache]; + [self setSharedPreconfiguredRemoteImageManager:sharedManager]; } -+ (PINRemoteImageManager *)sharedPINRemoteImageManagerWithConfiguration:(NSURLSessionConfiguration *)configuration preconfiguredPINRemoteImageManager:(PINRemoteImageManager *)preconfiguredPINRemoteImageManager -{ - NSAssert(!(configuration != nil && preconfiguredPINRemoteImageManager != nil), @"Either configuration or preconfigured image manager can be set at a time."); - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ +static dispatch_once_t shared_init_predicate; - if (preconfiguredPINRemoteImageManager) { - sharedPINRemoteImageManager = preconfiguredPINRemoteImageManager; - } else { -#if PIN_ANIMATED_AVAILABLE - // Check that Carthage users have linked both PINRemoteImage & PINCache by testing for one file each - if (!(NSClassFromString(@"PINRemoteImageManager"))) { - NSException *e = [NSException - exceptionWithName:@"FrameworkSetupException" - reason:@"Missing the path to the PINRemoteImage framework." - userInfo:nil]; - @throw e; - } - if (!(NSClassFromString(@"PINCache"))) { - NSException *e = [NSException - exceptionWithName:@"FrameworkSetupException" - reason:@"Missing the path to the PINCache framework." - userInfo:nil]; - @throw e; - } - sharedPINRemoteImageManager = [[ASPINRemoteImageManager alloc] initWithSessionConfiguration:configuration - alternativeRepresentationProvider:[self sharedDownloader]]; -#else - sharedPINRemoteImageManager = [[ASPINRemoteImageManager alloc] initWithSessionConfiguration:configuration]; -#endif - } ++ (void)setSharedPreconfiguredRemoteImageManager:(PINRemoteImageManager *)preconfiguredPINRemoteImageManager +{ + NSAssert(preconfiguredPINRemoteImageManager != nil, @"setSharedPreconfiguredRemoteImageManager requires a non-nil parameter"); + NSAssert(sharedDownloader == nil, @"Singleton has been created and session can no longer be configured."); + NSAssert1(sharedPINRemoteImageManager == nil, @"An instance of %@ has been set. Either configuration or preconfigured image manager can be set at a time and only once.", [[sharedPINRemoteImageManager class] description]); + + dispatch_once(&shared_init_predicate, ^{ + sharedPINRemoteImageManager = preconfiguredPINRemoteImageManager; }); - return sharedPINRemoteImageManager; +} + ++ (PINRemoteImageManager *)PINRemoteImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration imageCache:(nullable id)imageCache +{ + PINRemoteImageManager *manager = nil; +#if DEBUG + // Check that Carthage users have linked both PINRemoteImage & PINCache by testing for one file each + if (!(NSClassFromString(@"PINRemoteImageManager"))) { + NSException *e = [NSException + exceptionWithName:@"FrameworkSetupException" + reason:@"Missing the path to the PINRemoteImage framework." + userInfo:nil]; + @throw e; + } + if (!(NSClassFromString(@"PINCache"))) { + NSException *e = [NSException + exceptionWithName:@"FrameworkSetupException" + reason:@"Missing the path to the PINCache framework." + userInfo:nil]; + @throw e; + } +#endif +#if PIN_ANIMATED_AVAILABLE + manager = [[ASPINRemoteImageManager alloc] initWithSessionConfiguration:configuration + alternativeRepresentationProvider:[self sharedDownloader] + imageCache:imageCache]; +#else + manager = [[ASPINRemoteImageManager alloc] initWithSessionConfiguration:configuration + alternativeRepresentationProvider:nil + imageCache:imageCache]; +#endif + return manager; } - (PINRemoteImageManager *)sharedPINRemoteImageManager { - return [ASPINRemoteImageDownloader sharedPINRemoteImageManagerWithConfiguration:nil preconfiguredPINRemoteImageManager:nil]; + dispatch_once(&shared_init_predicate, ^{ + sharedPINRemoteImageManager = [ASPINRemoteImageDownloader PINRemoteImageManagerWithConfiguration:nil imageCache:nil]; + }); + return sharedPINRemoteImageManager; } - (BOOL)sharedImageManagerSupportsMemoryRemoval diff --git a/Source/Details/ASPageTable.m b/Source/Details/ASPageTable.mm similarity index 99% rename from Source/Details/ASPageTable.m rename to Source/Details/ASPageTable.mm index 15b43dca9f..af74d0c59e 100644 --- a/Source/Details/ASPageTable.m +++ b/Source/Details/ASPageTable.mm @@ -1,5 +1,5 @@ // -// ASPageTable.m +// ASPageTable.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Details/ASPhotosFrameworkImageRequest.m b/Source/Details/ASPhotosFrameworkImageRequest.mm similarity index 99% rename from Source/Details/ASPhotosFrameworkImageRequest.m rename to Source/Details/ASPhotosFrameworkImageRequest.mm index 942000bb6f..a7e0b41655 100644 --- a/Source/Details/ASPhotosFrameworkImageRequest.m +++ b/Source/Details/ASPhotosFrameworkImageRequest.mm @@ -1,5 +1,5 @@ // -// ASPhotosFrameworkImageRequest.m +// ASPhotosFrameworkImageRequest.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASRecursiveUnfairLock.h b/Source/Details/ASRecursiveUnfairLock.h index 48aab7f307..d705e4d384 100644 --- a/Source/Details/ASRecursiveUnfairLock.h +++ b/Source/Details/ASRecursiveUnfairLock.h @@ -11,11 +11,6 @@ #import #import -// Don't import C-only header if we're in a C++ file -#ifndef __cplusplus -#import -#endif - // Note: We don't use ATOMIC_VAR_INIT here because C++ compilers don't like it, // and it literally does absolutely nothing. #define AS_RECURSIVE_UNFAIR_LOCK_INIT ((ASRecursiveUnfairLock){ OS_UNFAIR_LOCK_INIT, NULL, 0}) @@ -24,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN OS_UNFAIR_LOCK_AVAILABILITY typedef struct { - os_unfair_lock _lock; + os_unfair_lock _lock OS_UNFAIR_LOCK_AVAILABILITY; _Atomic(pthread_t) _thread; // Write-protected by lock int _count; // Protected by lock } ASRecursiveUnfairLock; diff --git a/Source/Details/ASRecursiveUnfairLock.m b/Source/Details/ASRecursiveUnfairLock.mm similarity index 98% rename from Source/Details/ASRecursiveUnfairLock.m rename to Source/Details/ASRecursiveUnfairLock.mm index 7e5cac3681..9e4a29d47a 100644 --- a/Source/Details/ASRecursiveUnfairLock.m +++ b/Source/Details/ASRecursiveUnfairLock.mm @@ -1,5 +1,5 @@ // -// ASRecursiveUnfairLock.m +// ASRecursiveUnfairLock.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. @@ -8,6 +8,8 @@ #import "ASRecursiveUnfairLock.h" +#import + /** * For our atomic _thread, we use acquire/release memory order so that we can have * the minimum possible constraint on the hardware. The default, `memory_order_seq_cst` diff --git a/Source/Details/ASScrollDirection.m b/Source/Details/ASScrollDirection.mm similarity index 98% rename from Source/Details/ASScrollDirection.m rename to Source/Details/ASScrollDirection.mm index 4edc8ec259..3dff6ba9b8 100644 --- a/Source/Details/ASScrollDirection.m +++ b/Source/Details/ASScrollDirection.mm @@ -1,5 +1,5 @@ // -// ASScrollDirection.m +// ASScrollDirection.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASTableLayoutController.m b/Source/Details/ASTableLayoutController.mm similarity index 98% rename from Source/Details/ASTableLayoutController.m rename to Source/Details/ASTableLayoutController.mm index dd6d9d0302..0669c76131 100644 --- a/Source/Details/ASTableLayoutController.m +++ b/Source/Details/ASTableLayoutController.mm @@ -1,5 +1,5 @@ // -// ASTableLayoutController.m +// ASTableLayoutController.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASThread.h b/Source/Details/ASThread.h index bdcfd26189..d5896fd13b 100644 --- a/Source/Details/ASThread.h +++ b/Source/Details/ASThread.h @@ -9,11 +9,8 @@ #import -#import #import #import -#import -#import #import #import @@ -82,7 +79,7 @@ ASDISPLAYNODE_INLINE void _ASLockScopeUnownedCleanup(id __unsafe_unre #define ASSynthesizeLockingMethodsWithMutex(mutex) \ - (void)lock { mutex.lock(); } \ - (void)unlock { mutex.unlock(); } \ -- (BOOL)tryLock { return mutex.tryLock(); } +- (BOOL)tryLock { return (BOOL)mutex.try_lock(); } #define ASSynthesizeLockingMethodsWithObject(object) \ - (void)lock { [object lock]; } \ @@ -95,259 +92,118 @@ ASDISPLAYNODE_INLINE void _ASUnlockScopeCleanup(id __strong *lockPtr) #ifdef __cplusplus -#define TIME_LOCKER 0 -/** - * Enable this flag to collect information on the owning thread and ownership level of a mutex. - * These properties are useful to determine if a mutex has been acquired and in case of a recursive mutex, how many times that happened. - * - * This flag also enable locking assertions (e.g ASAssertUnlocked(node)). - * The assertions are useful when you want to indicate and enforce the locking policy/expectation of methods. - * To determine when and which methods acquired a (recursive) mutex (to debug deadlocks, for example), - * put breakpoints at some assertions. When the breakpoints hit, walk through stack trace frames - * and check ownership count of the mutex. - */ -#if ASDISPLAYNODE_ASSERTIONS_ENABLED -#define CHECK_LOCKING_SAFETY 1 -#else -#define CHECK_LOCKING_SAFETY 0 -#endif - -#if TIME_LOCKER -#import -#endif - #include +#include +#include +#include -// This MUST always execute, even when assertions are disabled. Otherwise all lock operations become no-ops! -// (To be explicit, do not turn this into an NSAssert, assert(), or any other kind of statement where the -// evaluation of x_ can be compiled out.) -#define AS_POSIX_ASSERT_NOERR(x_) ({ \ - __unused int res = (x_); \ - ASDisplayNodeCAssert(res == 0, @"Expected %s to return 0, got %d instead. Error: %s", #x_, res, strerror(res)); \ -}) - -/** - * Assert if the current thread owns a mutex. - * This assertion is useful when you want to indicate and enforce the locking policy/expectation of methods. - * To determine when and which methods acquired a (recursive) mutex (to debug deadlocks, for example), - * put breakpoints at some of these assertions. When the breakpoints hit, walk through stack trace frames - * and check ownership count of the mutex. - */ -#if CHECK_LOCKING_SAFETY -#define ASAssertUnlocked(lock) ASDisplayNodeAssertFalse(lock.locked()) -#define ASAssertLocked(lock) ASDisplayNodeAssert(lock.locked(), @"Lock must be held by current thread") -#else -#define ASAssertUnlocked(lock) -#define ASAssertLocked(lock) -#endif +// These macros are here for legacy reasons. We may get rid of them later. +#define ASAssertLocked(m) m.AssertHeld() +#define ASAssertUnlocked(m) m.AssertNotHeld() namespace ASDN { - template - class Locker - { - T &_l; - -#if TIME_LOCKER - CFTimeInterval _ti; - const char *_name; -#endif - - public: -#if !TIME_LOCKER - - Locker (T &l) noexcept : _l (l) { - _l.lock (); - } - - ~Locker () { - _l.unlock (); - } - - // non-copyable. - Locker(const Locker&) = delete; - Locker &operator=(const Locker&) = delete; - -#else - - Locker (T &l, const char *name = NULL) noexcept : _l (l), _name(name) { - _ti = CACurrentMediaTime(); - _l.lock (); - } - - ~Locker () { - _l.unlock (); - if (_name) { - printf(_name, NULL); - printf(" dt:%f\n", CACurrentMediaTime() - _ti); - } - } - -#endif - - }; - - template - class SharedLocker - { - std::shared_ptr _l; - -#if TIME_LOCKER - CFTimeInterval _ti; - const char *_name; -#endif - - public: -#if !TIME_LOCKER - - SharedLocker (std::shared_ptr const& l) noexcept : _l (l) { - ASDisplayNodeCAssertTrue(_l != nullptr); - _l->lock (); - } - - ~SharedLocker () { - _l->unlock (); - } - - // non-copyable. - SharedLocker(const SharedLocker&) = delete; - SharedLocker &operator=(const SharedLocker&) = delete; - -#else - - SharedLocker (std::shared_ptr const& l, const char *name = NULL) noexcept : _l (l), _name(name) { - _ti = CACurrentMediaTime(); - _l->lock (); - } - - ~SharedLocker () { - _l->unlock (); - if (_name) { - printf(_name, NULL); - printf(" dt:%f\n", CACurrentMediaTime() - _ti); - } - } - -#endif - - }; - - template - class Unlocker - { - T &_l; - public: - Unlocker (T &l) noexcept : _l (l) { _l.unlock (); } - ~Unlocker () {_l.lock ();} - Unlocker(Unlocker&) = delete; - Unlocker &operator=(Unlocker&) = delete; - }; - // Set once in Mutex constructor. Linker fails if this is a member variable. ?? - static BOOL gMutex_unfair; - + static bool gMutex_unfair; + // Silence unguarded availability warnings in here, because // perf is critical and we will check availability once // and not again. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability" - struct Mutex + class Mutex { - /// Constructs a non-recursive mutex (the default). + public: + /// Constructs a plain mutex (the default). Mutex () : Mutex (false) {} ~Mutex () { - if (gMutex_unfair) { - // nop - } else { - AS_POSIX_ASSERT_NOERR(pthread_mutex_destroy (&_m)); + // Manually destroy since unions can't do it. + switch (_type) { + case Plain: + _plain.~mutex(); + break; + case Recursive: + _recursive.~recursive_mutex(); + break; + case Unfair: + // nop + break; + case RecursiveUnfair: + // nop + break; } -#if CHECK_LOCKING_SAFETY - _owner = 0; - _count = 0; -#endif } Mutex (const Mutex&) = delete; Mutex &operator=(const Mutex&) = delete; - bool tryLock() { - if (gMutex_unfair) { - if (_recursive) { - return ASRecursiveUnfairLockTryLock(&_runfair); - } else { - return os_unfair_lock_trylock(&_unfair); - } - } else { - let result = pthread_mutex_trylock(&_m); - if (result == 0) { - return true; - } else if (result == EBUSY) { - return false; - } else { - ASDisplayNodeCFailAssert(@"Locking error: %s", strerror(result)); - return true; // if we return false we may enter an infinite loop. - } + bool try_lock() { + bool success = false; + switch (_type) { + case Plain: + success = _plain.try_lock(); + break; + case Recursive: + success = _recursive.try_lock(); + break; + case Unfair: + success = os_unfair_lock_trylock(&_unfair); + break; + case RecursiveUnfair: + success = ASRecursiveUnfairLockTryLock(&_runfair); + break; } + if (success) { + DidLock(); + } + return success; + } + + void lock() { + switch (_type) { + case Plain: + _plain.lock(); + break; + case Recursive: + _recursive.lock(); + break; + case Unfair: + os_unfair_lock_lock(&_unfair); + break; + case RecursiveUnfair: + ASRecursiveUnfairLockLock(&_runfair); + break; + } + DidLock(); + } + + void unlock() { + WillUnlock(); + switch (_type) { + case Plain: + _plain.unlock(); + break; + case Recursive: + _recursive.unlock(); + break; + case Unfair: + os_unfair_lock_unlock(&_unfair); + break; + case RecursiveUnfair: + ASRecursiveUnfairLockUnlock(&_runfair); + break; + } + } + + void AssertHeld() { + ASDisplayNodeCAssert(_owner == std::this_thread::get_id(), @"Thread should hold lock"); + } + + void AssertNotHeld() { + ASDisplayNodeCAssert(_owner != std::this_thread::get_id(), @"Thread should not hold lock"); } - void lock() { - if (gMutex_unfair) { - if (_recursive) { - ASRecursiveUnfairLockLock(&_runfair); - } else { - os_unfair_lock_lock(&_unfair); - } - } else { - AS_POSIX_ASSERT_NOERR(pthread_mutex_lock(&_m)); - } -#if CHECK_LOCKING_SAFETY - mach_port_t thread_id = pthread_mach_thread_np(pthread_self()); - if (thread_id != _owner) { - // New owner. Since this mutex can't be acquired by another thread if there is an existing owner, _owner and _count must be 0. - ASDisplayNodeCAssertTrue(0 == _owner); - ASDisplayNodeCAssertTrue(0 == _count); - _owner = thread_id; - } else { - // Existing owner tries to reacquire this (recursive) mutex. _count must already be positive. - ASDisplayNodeCAssertTrue(_count > 0); - } - ++_count; -#endif - } - - void unlock () { -#if CHECK_LOCKING_SAFETY - mach_port_t thread_id = pthread_mach_thread_np(pthread_self()); - // Unlocking a mutex on an unowning thread causes undefined behaviour. Assert and fail early. - ASDisplayNodeCAssertTrue(thread_id == _owner); - // Current thread owns this mutex. _count must be positive. - ASDisplayNodeCAssertTrue(_count > 0); - --_count; - if (0 == _count) { - // Current thread is no longer the owner. - _owner = 0; - } -#endif - if (gMutex_unfair) { - if (_recursive) { - ASRecursiveUnfairLockUnlock(&_runfair); - } else { - os_unfair_lock_unlock(&_unfair); - } - } else { - AS_POSIX_ASSERT_NOERR(pthread_mutex_unlock(&_m)); - } - } - - pthread_mutex_t *mutex () { return &_m; } - -#if CHECK_LOCKING_SAFETY - bool locked() { - return _count > 0 && pthread_mach_thread_np(pthread_self()) == _owner; - } -#endif - protected: explicit Mutex (bool recursive) { // Check if we can use unfair lock and store in static var. @@ -358,44 +214,60 @@ namespace ASDN { } }); - _recursive = recursive; - - if (gMutex_unfair) { - if (recursive) { + if (recursive) { + if (gMutex_unfair) { + _type = RecursiveUnfair; _runfair = AS_RECURSIVE_UNFAIR_LOCK_INIT; } else { - _unfair = OS_UNFAIR_LOCK_INIT; + _type = Recursive; + new (&_recursive) std::recursive_mutex(); } } else { - if (!recursive) { - AS_POSIX_ASSERT_NOERR(pthread_mutex_init (&_m, NULL)); + if (gMutex_unfair) { + _type = Unfair; + _unfair = OS_UNFAIR_LOCK_INIT; } else { - // Fall back to recursive mutex. - static pthread_mutexattr_t attr; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - AS_POSIX_ASSERT_NOERR(pthread_mutexattr_init (&attr)); - AS_POSIX_ASSERT_NOERR(pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE)); - }); - AS_POSIX_ASSERT_NOERR(pthread_mutex_init(&_m, &attr)); + _type = Plain; + new (&_plain) std::mutex(); } } -#if CHECK_LOCKING_SAFETY - _owner = 0; - _count = 0; -#endif } private: - BOOL _recursive; + enum Type { + Plain, + Recursive, + Unfair, + RecursiveUnfair + }; + + void WillUnlock() { +#if ASDISPLAYNODE_ASSERTIONS_ENABLED + if (--_count == 0) { + _owner = std::thread::id(); + } +#endif + } + + void DidLock() { +#if ASDISPLAYNODE_ASSERTIONS_ENABLED + if (++_count == 1) { + // New owner. + _owner = std::this_thread::get_id(); + } +#endif + } + + Type _type; union { os_unfair_lock _unfair; ASRecursiveUnfairLock _runfair; - pthread_mutex_t _m; + std::mutex _plain; + std::recursive_mutex _recursive; }; -#if CHECK_LOCKING_SAFETY - mach_port_t _owner; - uint32_t _count; +#if ASDISPLAYNODE_ASSERTIONS_ENABLED + std::thread::id _owner = std::thread::id(); + int _count = 0; #endif }; #pragma clang diagnostic pop // ignored "-Wunguarded-availability" @@ -409,46 +281,14 @@ namespace ASDN { http://www.zaval.org/resources/library/butenhof1.html http://www.fieryrobot.com/blog/2008/10/14/recursive-locks-will-kill-you/ */ - struct RecursiveMutex : Mutex + class RecursiveMutex : public Mutex { + public: RecursiveMutex () : Mutex (true) {} }; - typedef Locker MutexLocker; - typedef SharedLocker MutexSharedLocker; - typedef Unlocker MutexUnlocker; - - /** - If you are creating a static mutex, use StaticMutex. This avoids expensive constructor overhead at startup (or worse, ordering - issues between different static objects). It also avoids running a destructor on app exit time (needless expense). - - Note that you can, but should not, use StaticMutex for non-static objects. It will leak its mutex on destruction, - so avoid that! - */ - struct StaticMutex - { - StaticMutex () : _m (PTHREAD_MUTEX_INITIALIZER) {} - - // non-copyable. - StaticMutex(const StaticMutex&) = delete; - StaticMutex &operator=(const StaticMutex&) = delete; - - void lock () { - AS_POSIX_ASSERT_NOERR(pthread_mutex_lock (this->mutex())); - } - - void unlock () { - AS_POSIX_ASSERT_NOERR(pthread_mutex_unlock (this->mutex())); - } - - pthread_mutex_t *mutex () { return &_m; } - - private: - pthread_mutex_t _m; - }; - - typedef Locker StaticMutexLocker; - typedef Unlocker StaticMutexUnlocker; + typedef std::lock_guard MutexLocker; + typedef std::unique_lock UniqueLock; } // namespace ASDN diff --git a/Source/Details/ASTraceEvent.m b/Source/Details/ASTraceEvent.mm similarity index 99% rename from Source/Details/ASTraceEvent.m rename to Source/Details/ASTraceEvent.mm index 0325fbf901..c809865591 100644 --- a/Source/Details/ASTraceEvent.m +++ b/Source/Details/ASTraceEvent.mm @@ -1,5 +1,5 @@ // -// ASTraceEvent.m +// ASTraceEvent.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASTraitCollection.h b/Source/Details/ASTraitCollection.h index 72dedd616c..9ecf433ecc 100644 --- a/Source/Details/ASTraitCollection.h +++ b/Source/Details/ASTraitCollection.h @@ -18,34 +18,6 @@ NS_ASSUME_NONNULL_BEGIN -#pragma mark - ASPrimitiveContentSizeCategory - -/** - * ASPrimitiveContentSizeCategory is a UIContentSizeCategory that can be used inside a struct. - * - * We need an unretained pointer because ARC can't manage struct memory. - * - * WARNING: DO NOT cast UIContentSizeCategory values to ASPrimitiveContentSizeCategory directly. - * Use ASPrimitiveContentSizeCategoryMake(UIContentSizeCategory) instead. - * This is because we make some assumptions about the lifetime of the object it points to. - * Also note that cast from ASPrimitiveContentSizeCategory to UIContentSizeCategory is always safe. - */ -typedef __unsafe_unretained UIContentSizeCategory ASPrimitiveContentSizeCategory; - -/** - * Safely casts from UIContentSizeCategory to ASPrimitiveContentSizeCategory. - * - * The UIKit documentation doesn't specify if we can receive a copy of the UIContentSizeCategory constant. While getting - * copies is fine with ARC, usage of unretained pointers requires us to ensure the lifetime of the object it points to. - * Manual retain&release of the UIContentSizeCategory object is not an option because it would require us to do that - * everywhere ASPrimitiveTraitCollection is used. This is error-prone and can lead to crashes and memory leaks. So, we - * explicitly limit possible values of ASPrimitiveContentSizeCategory to the predetermined set of global constants with - * known lifetime. - * - * @return a pointer to one of the UIContentSizeCategory constants. - */ -AS_EXTERN ASPrimitiveContentSizeCategory ASPrimitiveContentSizeCategoryMake(UIContentSizeCategory sizeCategory); - #pragma mark - ASPrimitiveTraitCollection /** @@ -56,24 +28,28 @@ AS_EXTERN ASPrimitiveContentSizeCategory ASPrimitiveContentSizeCategoryMake(UICo * If you use ASPrimitiveTraitCollection, please do make sure to initialize it with ASPrimitiveTraitCollectionMakeDefault() * or ASPrimitiveTraitCollectionFromUITraitCollection(UITraitCollection*). */ -typedef struct ASPrimitiveTraitCollection { +#pragma clang diagnostic push +#pragma clang diagnostic warning "-Wpadded" +typedef struct { UIUserInterfaceSizeClass horizontalSizeClass; UIUserInterfaceSizeClass verticalSizeClass; CGFloat displayScale; - UIDisplayGamut displayGamut; + UIDisplayGamut displayGamut API_AVAILABLE(ios(10.0)); UIUserInterfaceIdiom userInterfaceIdiom; UIForceTouchCapability forceTouchCapability; - UITraitEnvironmentLayoutDirection layoutDirection; -#if TARGET_OS_TV - UIUserInterfaceStyle userInterfaceStyle; + UITraitEnvironmentLayoutDirection layoutDirection API_AVAILABLE(ios(10.0)); +#if AS_BUILD_UIUSERINTERFACESTYLE + UIUserInterfaceStyle userInterfaceStyle API_AVAILABLE(tvos(10.0), ios(12.0)); #endif - ASPrimitiveContentSizeCategory preferredContentSizeCategory; + // NOTE: This must be a constant. We will assert. + unowned UIContentSizeCategory preferredContentSizeCategory API_AVAILABLE(ios(10.0)); CGSize containerSize; } ASPrimitiveTraitCollection; +#pragma clang diagnostic pop /** * Creates ASPrimitiveTraitCollection with default values. @@ -164,52 +140,21 @@ AS_EXTERN void ASTraitCollectionPropagateDown(id element, ASPri AS_SUBCLASSING_RESTRICTED @interface ASTraitCollection : NSObject -@property (nonatomic, readonly) UIUserInterfaceSizeClass horizontalSizeClass; -@property (nonatomic, readonly) UIUserInterfaceSizeClass verticalSizeClass; +@property (readonly) UIUserInterfaceSizeClass horizontalSizeClass; +@property (readonly) UIUserInterfaceSizeClass verticalSizeClass; -@property (nonatomic, readonly) CGFloat displayScale; -@property (nonatomic, readonly) UIDisplayGamut displayGamut; +@property (readonly) CGFloat displayScale; +@property (readonly) UIDisplayGamut displayGamut API_AVAILABLE(ios(10.0)); -@property (nonatomic, readonly) UIUserInterfaceIdiom userInterfaceIdiom; -@property (nonatomic, readonly) UIForceTouchCapability forceTouchCapability; -@property (nonatomic, readonly) UITraitEnvironmentLayoutDirection layoutDirection; -#if TARGET_OS_TV -@property (nonatomic, readonly) UIUserInterfaceStyle userInterfaceStyle; +@property (readonly) UIUserInterfaceIdiom userInterfaceIdiom; +@property (readonly) UIForceTouchCapability forceTouchCapability; +@property (readonly) UITraitEnvironmentLayoutDirection layoutDirection API_AVAILABLE(ios(10.0)); +#if AS_BUILD_UIUSERINTERFACESTYLE +@property (readonly) UIUserInterfaceStyle userInterfaceStyle API_AVAILABLE(tvos(10.0), ios(12.0)); #endif +@property (readonly) UIContentSizeCategory preferredContentSizeCategory API_AVAILABLE(ios(10.0)); -@property (nonatomic, readonly) UIContentSizeCategory preferredContentSizeCategory; - -@property (nonatomic, readonly) CGSize containerSize; - -+ (ASTraitCollection *)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection - containerSize:(CGSize)windowSize NS_RETURNS_RETAINED; - -+ (ASTraitCollection *)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection - containerSize:(CGSize)windowSize - fallbackContentSizeCategory:(UIContentSizeCategory)fallbackContentSizeCategory NS_RETURNS_RETAINED; - -#if TARGET_OS_TV -+ (ASTraitCollection *)traitCollectionWithHorizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass - verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass - displayScale:(CGFloat)displayScale - displayGamut:(UIDisplayGamut)displayGamut - userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom - forceTouchCapability:(UIForceTouchCapability)forceTouchCapability - layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection - userInterfaceStyle:(UIUserInterfaceStyle)userInterfaceStyle - preferredContentSizeCategory:(UIContentSizeCategory)preferredContentSizeCategory - containerSize:(CGSize)windowSize NS_RETURNS_RETAINED; -#else -+ (ASTraitCollection *)traitCollectionWithHorizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass - verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass - displayScale:(CGFloat)displayScale - displayGamut:(UIDisplayGamut)displayGamut - userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom - forceTouchCapability:(UIForceTouchCapability)forceTouchCapability - layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection - preferredContentSizeCategory:(UIContentSizeCategory)preferredContentSizeCategory - containerSize:(CGSize)windowSize NS_RETURNS_RETAINED; -#endif +@property (readonly) CGSize containerSize; - (BOOL)isEqualToTraitCollection:(ASTraitCollection *)traitCollection; @@ -226,18 +171,4 @@ AS_SUBCLASSING_RESTRICTED @end -@interface ASTraitCollection (Deprecated) - -- (instancetype)init ASDISPLAYNODE_DEPRECATED_MSG("The default constructor of this class is going to become unavailable. Use other constructors instead."); - -+ (ASTraitCollection *)traitCollectionWithDisplayScale:(CGFloat)displayScale - userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom - horizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass - verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass - forceTouchCapability:(UIForceTouchCapability)forceTouchCapability - containerSize:(CGSize)windowSize - NS_RETURNS_RETAINED ASDISPLAYNODE_DEPRECATED_MSG("Use full version of this method instead."); - -@end - NS_ASSUME_NONNULL_END diff --git a/Source/Details/ASTraitCollection.m b/Source/Details/ASTraitCollection.m deleted file mode 100644 index 56c29c5cbe..0000000000 --- a/Source/Details/ASTraitCollection.m +++ /dev/null @@ -1,535 +0,0 @@ -// -// ASTraitCollection.m -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import - -#pragma mark - ASPrimitiveContentSizeCategory - -// UIContentSizeCategoryUnspecified is available only in iOS 10.0 and later. -// This is used for compatibility with older iOS versions. -ASDISPLAYNODE_INLINE UIContentSizeCategory AS_UIContentSizeCategoryUnspecified() { - if (AS_AVAILABLE_IOS(10)) { - return UIContentSizeCategoryUnspecified; - } else { - return @"_UICTContentSizeCategoryUnspecified"; - } -} - -ASDISPLAYNODE_INLINE UIContentSizeCategory _Nonnull AS_safeContentSizeCategory(UIContentSizeCategory _Nullable sizeCategory) { - return sizeCategory ? sizeCategory : AS_UIContentSizeCategoryUnspecified(); -} - -ASPrimitiveContentSizeCategory ASPrimitiveContentSizeCategoryMake(UIContentSizeCategory sizeCategory) { - if ([sizeCategory isEqualToString:UIContentSizeCategoryExtraSmall]) { - return UIContentSizeCategoryExtraSmall; - } - if ([sizeCategory isEqualToString:UIContentSizeCategorySmall]) { - return UIContentSizeCategorySmall; - } - if ([sizeCategory isEqualToString:UIContentSizeCategoryMedium]) { - return UIContentSizeCategoryMedium; - } - if ([sizeCategory isEqualToString:UIContentSizeCategoryLarge]) { - return UIContentSizeCategoryLarge; - } - if ([sizeCategory isEqualToString:UIContentSizeCategoryExtraLarge]) { - return UIContentSizeCategoryExtraLarge; - } - if ([sizeCategory isEqualToString:UIContentSizeCategoryExtraExtraLarge]) { - return UIContentSizeCategoryExtraExtraLarge; - } - if ([sizeCategory isEqualToString:UIContentSizeCategoryExtraExtraExtraLarge]) { - return UIContentSizeCategoryExtraExtraExtraLarge; - } - - if ([sizeCategory isEqualToString:UIContentSizeCategoryAccessibilityMedium]) { - return UIContentSizeCategoryAccessibilityMedium; - } - if ([sizeCategory isEqualToString:UIContentSizeCategoryAccessibilityLarge]) { - return UIContentSizeCategoryAccessibilityLarge; - } - if ([sizeCategory isEqualToString:UIContentSizeCategoryAccessibilityExtraLarge]) { - return UIContentSizeCategoryAccessibilityExtraLarge; - } - if ([sizeCategory isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraLarge]) { - return UIContentSizeCategoryAccessibilityExtraExtraLarge; - } - if ([sizeCategory isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraExtraLarge]) { - return UIContentSizeCategoryAccessibilityExtraExtraExtraLarge; - } - - return AS_UIContentSizeCategoryUnspecified(); -} - -#pragma mark - ASPrimitiveTraitCollection - -void ASTraitCollectionPropagateDown(id element, ASPrimitiveTraitCollection traitCollection) { - if (element) { - element.primitiveTraitCollection = traitCollection; - } - - for (id subelement in element.sublayoutElements) { - ASTraitCollectionPropagateDown(subelement, traitCollection); - } -} - -ASPrimitiveTraitCollection ASPrimitiveTraitCollectionMakeDefault() { - return (ASPrimitiveTraitCollection) { - // Default values can be defined in here - .displayGamut = UIDisplayGamutUnspecified, - .userInterfaceIdiom = UIUserInterfaceIdiomUnspecified, - .layoutDirection = UITraitEnvironmentLayoutDirectionUnspecified, - .preferredContentSizeCategory = ASPrimitiveContentSizeCategoryMake(AS_UIContentSizeCategoryUnspecified()), - .containerSize = CGSizeZero, - }; -} - -ASPrimitiveTraitCollection ASPrimitiveTraitCollectionFromUITraitCollection(UITraitCollection *traitCollection) { - ASPrimitiveTraitCollection environmentTraitCollection = ASPrimitiveTraitCollectionMakeDefault(); - environmentTraitCollection.horizontalSizeClass = traitCollection.horizontalSizeClass; - environmentTraitCollection.verticalSizeClass = traitCollection.verticalSizeClass; - environmentTraitCollection.displayScale = traitCollection.displayScale; - environmentTraitCollection.userInterfaceIdiom = traitCollection.userInterfaceIdiom; - environmentTraitCollection.forceTouchCapability = traitCollection.forceTouchCapability; - if (AS_AVAILABLE_IOS(10)) { - environmentTraitCollection.displayGamut = traitCollection.displayGamut; - environmentTraitCollection.layoutDirection = traitCollection.layoutDirection; - - // preferredContentSizeCategory is also available on older iOS versions, but only via UIApplication class. - // It should be noted that [UIApplication sharedApplication] is unavailable because Texture is built with only extension-safe API. - environmentTraitCollection.preferredContentSizeCategory = ASPrimitiveContentSizeCategoryMake(traitCollection.preferredContentSizeCategory); - - #if TARGET_OS_TV - environmentTraitCollection.userInterfaceStyle = traitCollection.userInterfaceStyle; - #endif - } else { - environmentTraitCollection.displayGamut = UIDisplayGamutSRGB; // We're on iOS 9 or lower, so this is not a P3 device. - } - return environmentTraitCollection; -} - -BOOL ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(ASPrimitiveTraitCollection lhs, ASPrimitiveTraitCollection rhs) { - UIContentSizeCategory leftSizeCategory = AS_safeContentSizeCategory(lhs.preferredContentSizeCategory); - UIContentSizeCategory rightSizeCategory = AS_safeContentSizeCategory(rhs.preferredContentSizeCategory); - - return - lhs.verticalSizeClass == rhs.verticalSizeClass && - lhs.horizontalSizeClass == rhs.horizontalSizeClass && - lhs.displayScale == rhs.displayScale && - lhs.displayGamut == rhs.displayGamut && - lhs.userInterfaceIdiom == rhs.userInterfaceIdiom && - lhs.forceTouchCapability == rhs.forceTouchCapability && - lhs.layoutDirection == rhs.layoutDirection && - #if TARGET_OS_TV - lhs.userInterfaceStyle == rhs.userInterfaceStyle && - #endif - - [leftSizeCategory isEqualToString:rightSizeCategory] && // Simple pointer comparison should be sufficient here - - CGSizeEqualToSize(lhs.containerSize, rhs.containerSize); -} - -// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline -ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceIdiom(UIUserInterfaceIdiom idiom) { - switch (idiom) { - case UIUserInterfaceIdiomTV: - return @"TV"; - case UIUserInterfaceIdiomPad: - return @"Pad"; - case UIUserInterfaceIdiomPhone: - return @"Phone"; - case UIUserInterfaceIdiomCarPlay: - return @"CarPlay"; - default: - return @"Unspecified"; - } -} - -// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline -ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIForceTouchCapability(UIForceTouchCapability capability) { - switch (capability) { - case UIForceTouchCapabilityAvailable: - return @"Available"; - case UIForceTouchCapabilityUnavailable: - return @"Unavailable"; - default: - return @"Unknown"; - } -} - -// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline -ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceSizeClass(UIUserInterfaceSizeClass sizeClass) { - switch (sizeClass) { - case UIUserInterfaceSizeClassCompact: - return @"Compact"; - case UIUserInterfaceSizeClassRegular: - return @"Regular"; - default: - return @"Unspecified"; - } -} - -// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline -ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIDisplayGamut(UIDisplayGamut displayGamut) { - switch (displayGamut) { - case UIDisplayGamutSRGB: - return @"sRGB"; - case UIDisplayGamutP3: - return @"P3"; - default: - return @"Unspecified"; - } -} - -// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline -ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUITraitEnvironmentLayoutDirection(UITraitEnvironmentLayoutDirection layoutDirection) { - switch (layoutDirection) { - case UITraitEnvironmentLayoutDirectionLeftToRight: - return @"LeftToRight"; - case UITraitEnvironmentLayoutDirectionRightToLeft: - return @"RightToLeft"; - default: - return @"Unspecified"; - } -} - -#if TARGET_OS_TV -// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline -ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceStyle(UIUserInterfaceStyle userInterfaceStyle) { - switch (userInterfaceStyle) { - case UIUserInterfaceStyleLight: - return @"Light"; - case UIUserInterfaceStyleDark: - return @"Dark"; - default: - return @"Unspecified"; - } -} -#endif - -NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection traits) { - NSMutableArray *props = [NSMutableArray array]; - [props addObject:@{ @"verticalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.verticalSizeClass) }]; - [props addObject:@{ @"horizontalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.horizontalSizeClass) }]; - [props addObject:@{ @"displayScale": [NSString stringWithFormat: @"%.0lf", (double)traits.displayScale] }]; - [props addObject:@{ @"displayGamut": AS_NSStringFromUIDisplayGamut(traits.displayGamut) }]; - [props addObject:@{ @"userInterfaceIdiom": AS_NSStringFromUIUserInterfaceIdiom(traits.userInterfaceIdiom) }]; - [props addObject:@{ @"forceTouchCapability": AS_NSStringFromUIForceTouchCapability(traits.forceTouchCapability) }]; - [props addObject:@{ @"layoutDirection": AS_NSStringFromUITraitEnvironmentLayoutDirection(traits.layoutDirection) }]; - #if TARGET_OS_TV - [props addObject:@{ @"userInterfaceStyle": AS_NSStringFromUIUserInterfaceStyle(traits.userInterfaceStyle) }]; - #endif - [props addObject:@{ @"preferredContentSizeCategory": AS_safeContentSizeCategory(traits.preferredContentSizeCategory) }]; - [props addObject:@{ @"containerSize": NSStringFromCGSize(traits.containerSize) }]; - return ASObjectDescriptionMakeWithoutObject(props); -} - -#pragma mark - ASTraitCollection - -@implementation ASTraitCollection - -#if TARGET_OS_TV - -- (instancetype)initWithHorizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass - verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass - displayScale:(CGFloat)displayScale - displayGamut:(UIDisplayGamut)displayGamut - userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom - forceTouchCapability:(UIForceTouchCapability)forceTouchCapability - layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection - userInterfaceStyle:(UIUserInterfaceStyle)userInterfaceStyle - preferredContentSizeCategory:(UIContentSizeCategory _Nonnull)preferredContentSizeCategory - containerSize:(CGSize)windowSize -{ - self = [super init]; - if (self) { - _horizontalSizeClass = horizontalSizeClass; - _verticalSizeClass = verticalSizeClass; - _displayScale = displayScale; - _displayGamut = displayGamut; - _userInterfaceIdiom = userInterfaceIdiom; - _forceTouchCapability = forceTouchCapability; - _layoutDirection = layoutDirection; - _userInterfaceStyle = userInterfaceStyle; - _preferredContentSizeCategory = AS_safeContentSizeCategory(preferredContentSizeCategory); // guard against misuse - _containerSize = windowSize; - } - return self; -} - -+ (instancetype)traitCollectionWithHorizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass - verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass - displayScale:(CGFloat)displayScale - displayGamut:(UIDisplayGamut)displayGamut - userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom - forceTouchCapability:(UIForceTouchCapability)forceTouchCapability - layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection - userInterfaceStyle:(UIUserInterfaceStyle)userInterfaceStyle - preferredContentSizeCategory:(UIContentSizeCategory _Nonnull)preferredContentSizeCategory - containerSize:(CGSize)windowSize NS_RETURNS_RETAINED -{ - return [[self alloc] initWithHorizontalSizeClass:horizontalSizeClass - verticalSizeClass:verticalSizeClass - displayScale:displayScale - displayGamut:displayGamut - userInterfaceIdiom:userInterfaceIdiom - forceTouchCapability:forceTouchCapability - layoutDirection:layoutDirection - userInterfaceStyle:userInterfaceStyle - preferredContentSizeCategory:preferredContentSizeCategory - containerSize:windowSize]; -} - -#else - -- (instancetype)initWithHorizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass - verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass - displayScale:(CGFloat)displayScale - displayGamut:(UIDisplayGamut)displayGamut - userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom - forceTouchCapability:(UIForceTouchCapability)forceTouchCapability - layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection - preferredContentSizeCategory:(UIContentSizeCategory _Nonnull)preferredContentSizeCategory - containerSize:(CGSize)windowSize -{ - self = [super init]; - if (self) { - _horizontalSizeClass = horizontalSizeClass; - _verticalSizeClass = verticalSizeClass; - _displayScale = displayScale; - _displayGamut = displayGamut; - _userInterfaceIdiom = userInterfaceIdiom; - _forceTouchCapability = forceTouchCapability; - _layoutDirection = layoutDirection; - _preferredContentSizeCategory = AS_safeContentSizeCategory(preferredContentSizeCategory); // guard against misuse - _containerSize = windowSize; - } - return self; -} - -+ (instancetype)traitCollectionWithHorizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass - verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass - displayScale:(CGFloat)displayScale - displayGamut:(UIDisplayGamut)displayGamut - userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom - forceTouchCapability:(UIForceTouchCapability)forceTouchCapability - layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection - preferredContentSizeCategory:(UIContentSizeCategory _Nonnull)preferredContentSizeCategory - containerSize:(CGSize)windowSize NS_RETURNS_RETAINED -{ - return [[self alloc] initWithHorizontalSizeClass:horizontalSizeClass - verticalSizeClass:verticalSizeClass - displayScale:displayScale - displayGamut:displayGamut - userInterfaceIdiom:userInterfaceIdiom - forceTouchCapability:forceTouchCapability - layoutDirection:layoutDirection - preferredContentSizeCategory:preferredContentSizeCategory - containerSize:windowSize]; -} - -#endif - -+ (instancetype)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection - containerSize:(CGSize)windowSize NS_RETURNS_RETAINED -{ - return [self traitCollectionWithUITraitCollection:traitCollection - containerSize:windowSize - fallbackContentSizeCategory:AS_UIContentSizeCategoryUnspecified()]; -} - - -+ (instancetype)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection - containerSize:(CGSize)windowSize - fallbackContentSizeCategory:(UIContentSizeCategory _Nonnull)fallbackContentSizeCategory NS_RETURNS_RETAINED -{ - UIDisplayGamut displayGamut; - UITraitEnvironmentLayoutDirection layoutDirection; - UIContentSizeCategory sizeCategory; - #if TARGET_OS_TV - UIUserInterfaceStyle userInterfaceStyle; - #endif - if (AS_AVAILABLE_IOS(10)) { - displayGamut = traitCollection.displayGamut; - layoutDirection = traitCollection.layoutDirection; - sizeCategory = traitCollection.preferredContentSizeCategory; - #if TARGET_OS_TV - userInterfaceStyle = traitCollection.userInterfaceStyle; - #endif - } else { - displayGamut = UIDisplayGamutSRGB; // We're on iOS 9 or lower, so this is not a P3 device. - layoutDirection = UITraitEnvironmentLayoutDirectionUnspecified; - sizeCategory = fallbackContentSizeCategory; - #if TARGET_OS_TV - userInterfaceStyle = UIUserInterfaceStyleUnspecified; - #endif - } - -#if TARGET_OS_TV - return [self traitCollectionWithHorizontalSizeClass:traitCollection.horizontalSizeClass - verticalSizeClass:traitCollection.verticalSizeClass - displayScale:traitCollection.displayScale - displayGamut:displayGamut - userInterfaceIdiom:traitCollection.userInterfaceIdiom - forceTouchCapability:traitCollection.forceTouchCapability - layoutDirection:layoutDirection - userInterfaceStyle:userInterfaceStyle - preferredContentSizeCategory:sizeCategory - containerSize:windowSize]; -#else - return [self traitCollectionWithHorizontalSizeClass:traitCollection.horizontalSizeClass - verticalSizeClass:traitCollection.verticalSizeClass - displayScale:traitCollection.displayScale - displayGamut:displayGamut - userInterfaceIdiom:traitCollection.userInterfaceIdiom - forceTouchCapability:traitCollection.forceTouchCapability - layoutDirection:layoutDirection - preferredContentSizeCategory:sizeCategory - containerSize:windowSize]; -#endif -} - -- (BOOL)isEqualToTraitCollection:(ASTraitCollection *)traitCollection -{ - if (traitCollection == nil) { - return NO; - } - - if (self == traitCollection) { - return YES; - } - - return - self.horizontalSizeClass == traitCollection.horizontalSizeClass && - self.verticalSizeClass == traitCollection.verticalSizeClass && - self.displayScale == traitCollection.displayScale && - self.displayGamut == traitCollection.displayGamut && - self.userInterfaceIdiom == traitCollection.userInterfaceIdiom && - self.forceTouchCapability == traitCollection.forceTouchCapability && - self.layoutDirection == traitCollection.layoutDirection && - #if TARGET_OS_TV - self.userInterfaceStyle == traitCollection.userInterfaceStyle && - #endif - [self.preferredContentSizeCategory isEqualToString:traitCollection.preferredContentSizeCategory] && - CGSizeEqualToSize(self.containerSize, traitCollection.containerSize); -} - -@end - -@implementation ASTraitCollection (PrimitiveTraits) - -+ (instancetype)traitCollectionWithASPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traits NS_RETURNS_RETAINED -{ -#if TARGET_OS_TV - return [self traitCollectionWithHorizontalSizeClass:traits.horizontalSizeClass - verticalSizeClass:traits.verticalSizeClass - displayScale:traits.displayScale - displayGamut:traits.displayGamut - userInterfaceIdiom:traits.userInterfaceIdiom - forceTouchCapability:traits.forceTouchCapability - layoutDirection:traits.layoutDirection - userInterfaceStyle:traits.userInterfaceStyle - preferredContentSizeCategory:AS_safeContentSizeCategory(traits.preferredContentSizeCategory) - containerSize:traits.containerSize]; -#else - return [self traitCollectionWithHorizontalSizeClass:traits.horizontalSizeClass - verticalSizeClass:traits.verticalSizeClass - displayScale:traits.displayScale - displayGamut:traits.displayGamut - userInterfaceIdiom:traits.userInterfaceIdiom - forceTouchCapability:traits.forceTouchCapability - layoutDirection:traits.layoutDirection - preferredContentSizeCategory:AS_safeContentSizeCategory(traits.preferredContentSizeCategory) - containerSize:traits.containerSize]; -#endif -} - -- (ASPrimitiveTraitCollection)primitiveTraitCollection -{ - return (ASPrimitiveTraitCollection) { - .horizontalSizeClass = self.horizontalSizeClass, - .verticalSizeClass = self.verticalSizeClass, - .displayScale = self.displayScale, - .displayGamut = self.displayGamut, - .userInterfaceIdiom = self.userInterfaceIdiom, - .forceTouchCapability = self.forceTouchCapability, - .layoutDirection = self.layoutDirection, -#if TARGET_OS_TV - .userInterfaceStyle = self.userInterfaceStyle, -#endif - .preferredContentSizeCategory = ASPrimitiveContentSizeCategoryMake(self.preferredContentSizeCategory), - .containerSize = self.containerSize, - }; -} - -@end - -@implementation ASTraitCollection (Deprecated) - -- (instancetype)init -{ -#if TARGET_OS_TV - return [self initWithHorizontalSizeClass:UIUserInterfaceSizeClassUnspecified - verticalSizeClass:UIUserInterfaceSizeClassUnspecified - displayScale:0 - displayGamut:UIDisplayGamutUnspecified - userInterfaceIdiom:UIUserInterfaceIdiomUnspecified - forceTouchCapability:UIForceTouchCapabilityUnknown - layoutDirection:UITraitEnvironmentLayoutDirectionUnspecified - userInterfaceStyle:UIUserInterfaceStyleUnspecified - preferredContentSizeCategory:AS_UIContentSizeCategoryUnspecified() - containerSize:CGSizeZero]; -#else - return [self initWithHorizontalSizeClass:UIUserInterfaceSizeClassUnspecified - verticalSizeClass:UIUserInterfaceSizeClassUnspecified - displayScale:0 - displayGamut:UIDisplayGamutUnspecified - userInterfaceIdiom:UIUserInterfaceIdiomUnspecified - forceTouchCapability:UIForceTouchCapabilityUnknown - layoutDirection:UITraitEnvironmentLayoutDirectionUnspecified - preferredContentSizeCategory:AS_UIContentSizeCategoryUnspecified() - containerSize:CGSizeZero]; -#endif -} - -+ (ASTraitCollection *)traitCollectionWithDisplayScale:(CGFloat)displayScale - userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom - horizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass - verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass - forceTouchCapability:(UIForceTouchCapability)forceTouchCapability - containerSize:(CGSize)windowSize NS_RETURNS_RETAINED -{ -#if TARGET_OS_TV - return [self traitCollectionWithHorizontalSizeClass:horizontalSizeClass - verticalSizeClass:verticalSizeClass - displayScale:displayScale - displayGamut:UIDisplayGamutUnspecified - userInterfaceIdiom:userInterfaceIdiom - forceTouchCapability:forceTouchCapability - layoutDirection:UITraitEnvironmentLayoutDirectionUnspecified - userInterfaceStyle:UIUserInterfaceStyleUnspecified - preferredContentSizeCategory:AS_UIContentSizeCategoryUnspecified() - containerSize:windowSize]; -#else - return [self traitCollectionWithHorizontalSizeClass:horizontalSizeClass - verticalSizeClass:verticalSizeClass - displayScale:displayScale - displayGamut:UIDisplayGamutUnspecified - userInterfaceIdiom:userInterfaceIdiom - forceTouchCapability:forceTouchCapability - layoutDirection:UITraitEnvironmentLayoutDirectionUnspecified - preferredContentSizeCategory:AS_UIContentSizeCategoryUnspecified() - containerSize:windowSize]; -#endif -} - -@end diff --git a/Source/Details/ASTraitCollection.mm b/Source/Details/ASTraitCollection.mm new file mode 100644 index 0000000000..7058501aac --- /dev/null +++ b/Source/Details/ASTraitCollection.mm @@ -0,0 +1,249 @@ +// +// ASTraitCollection.mm +// Texture +// +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import +#import +#import +#import +#import + +#pragma mark - ASPrimitiveTraitCollection + +void ASTraitCollectionPropagateDown(id element, ASPrimitiveTraitCollection traitCollection) { + if (element) { + element.primitiveTraitCollection = traitCollection; + } + + for (id subelement in element.sublayoutElements) { + ASTraitCollectionPropagateDown(subelement, traitCollection); + } +} + +ASPrimitiveTraitCollection ASPrimitiveTraitCollectionMakeDefault() { + ASPrimitiveTraitCollection tc; + tc.horizontalSizeClass = UIUserInterfaceSizeClassUnspecified; + tc.verticalSizeClass = UIUserInterfaceSizeClassUnspecified; + tc.containerSize = CGSizeZero; + if (AS_AVAILABLE_IOS(10)) { + tc.displayGamut = UIDisplayGamutUnspecified; + tc.preferredContentSizeCategory = UIContentSizeCategoryUnspecified; + tc.layoutDirection = UITraitEnvironmentLayoutDirectionUnspecified; + } +#if AS_BUILD_UIUSERINTERFACESTYLE + if (AS_AVAILABLE_IOS_TVOS(12, 10)) { + tc.userInterfaceStyle = UIUserInterfaceStyleUnspecified; + } +#endif + return tc; +} + +ASPrimitiveTraitCollection ASPrimitiveTraitCollectionFromUITraitCollection(UITraitCollection *traitCollection) { + ASPrimitiveTraitCollection environmentTraitCollection = ASPrimitiveTraitCollectionMakeDefault(); + environmentTraitCollection.horizontalSizeClass = traitCollection.horizontalSizeClass; + environmentTraitCollection.verticalSizeClass = traitCollection.verticalSizeClass; + environmentTraitCollection.displayScale = traitCollection.displayScale; + environmentTraitCollection.userInterfaceIdiom = traitCollection.userInterfaceIdiom; + environmentTraitCollection.forceTouchCapability = traitCollection.forceTouchCapability; + if (AS_AVAILABLE_IOS(10)) { + environmentTraitCollection.displayGamut = traitCollection.displayGamut; + environmentTraitCollection.layoutDirection = traitCollection.layoutDirection; + + ASDisplayNodeCAssertPermanent(traitCollection.preferredContentSizeCategory); + environmentTraitCollection.preferredContentSizeCategory = traitCollection.preferredContentSizeCategory; + } +#if AS_BUILD_UIUSERINTERFACESTYLE + if (AS_AVAILABLE_IOS_TVOS(12, 10)) { + environmentTraitCollection.userInterfaceStyle = traitCollection.userInterfaceStyle; + } +#endif + return environmentTraitCollection; +} + +BOOL ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(ASPrimitiveTraitCollection lhs, ASPrimitiveTraitCollection rhs) { + return !memcmp(&lhs, &rhs, sizeof(ASPrimitiveTraitCollection)); +} + +// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline +ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceIdiom(UIUserInterfaceIdiom idiom) { + switch (idiom) { + case UIUserInterfaceIdiomTV: + return @"TV"; + case UIUserInterfaceIdiomPad: + return @"Pad"; + case UIUserInterfaceIdiomPhone: + return @"Phone"; + case UIUserInterfaceIdiomCarPlay: + return @"CarPlay"; + default: + return @"Unspecified"; + } +} + +// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline +ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIForceTouchCapability(UIForceTouchCapability capability) { + switch (capability) { + case UIForceTouchCapabilityAvailable: + return @"Available"; + case UIForceTouchCapabilityUnavailable: + return @"Unavailable"; + default: + return @"Unknown"; + } +} + +// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline +ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceSizeClass(UIUserInterfaceSizeClass sizeClass) { + switch (sizeClass) { + case UIUserInterfaceSizeClassCompact: + return @"Compact"; + case UIUserInterfaceSizeClassRegular: + return @"Regular"; + default: + return @"Unspecified"; + } +} + +// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline +API_AVAILABLE(ios(10)) +ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIDisplayGamut(UIDisplayGamut displayGamut) { + switch (displayGamut) { + case UIDisplayGamutSRGB: + return @"sRGB"; + case UIDisplayGamutP3: + return @"P3"; + default: + return @"Unspecified"; + } +} + +// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline +API_AVAILABLE(ios(10)) +ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUITraitEnvironmentLayoutDirection(UITraitEnvironmentLayoutDirection layoutDirection) { + switch (layoutDirection) { + case UITraitEnvironmentLayoutDirectionLeftToRight: + return @"LeftToRight"; + case UITraitEnvironmentLayoutDirectionRightToLeft: + return @"RightToLeft"; + default: + return @"Unspecified"; + } +} + +// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline +#if AS_BUILD_UIUSERINTERFACESTYLE +API_AVAILABLE(tvos(10.0), ios(12.0)) +ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceStyle(UIUserInterfaceStyle userInterfaceStyle) { + switch (userInterfaceStyle) { + case UIUserInterfaceStyleLight: + return @"Light"; + case UIUserInterfaceStyleDark: + return @"Dark"; + default: + return @"Unspecified"; + } +} +#endif + +NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection traits) { + NSMutableArray *props = [NSMutableArray array]; + [props addObject:@{ @"verticalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.verticalSizeClass) }]; + [props addObject:@{ @"horizontalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.horizontalSizeClass) }]; + [props addObject:@{ @"displayScale": [NSString stringWithFormat: @"%.0lf", (double)traits.displayScale] }]; + [props addObject:@{ @"userInterfaceIdiom": AS_NSStringFromUIUserInterfaceIdiom(traits.userInterfaceIdiom) }]; + [props addObject:@{ @"forceTouchCapability": AS_NSStringFromUIForceTouchCapability(traits.forceTouchCapability) }]; +#if AS_BUILD_UIUSERINTERFACESTYLE + if (AS_AVAILABLE_IOS_TVOS(12, 10)) { + [props addObject:@{ @"userInterfaceStyle": AS_NSStringFromUIUserInterfaceStyle(traits.userInterfaceStyle) }]; + } +#endif + if (AS_AVAILABLE_IOS(10)) { + [props addObject:@{ @"layoutDirection": AS_NSStringFromUITraitEnvironmentLayoutDirection(traits.layoutDirection) }]; + [props addObject:@{ @"preferredContentSizeCategory": traits.preferredContentSizeCategory }]; + [props addObject:@{ @"displayGamut": AS_NSStringFromUIDisplayGamut(traits.displayGamut) }]; + } + [props addObject:@{ @"containerSize": NSStringFromCGSize(traits.containerSize) }]; + return ASObjectDescriptionMakeWithoutObject(props); +} + +#pragma mark - ASTraitCollection + +@implementation ASTraitCollection { + ASPrimitiveTraitCollection _prim; +} + ++ (ASTraitCollection *)traitCollectionWithASPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traits NS_RETURNS_RETAINED { + ASTraitCollection *tc = [[ASTraitCollection alloc] init]; + if (AS_AVAILABLE_IOS(10)) { + ASDisplayNodeCAssertPermanent(traits.preferredContentSizeCategory); + } + tc->_prim = traits; + return tc; +} + +- (ASPrimitiveTraitCollection)primitiveTraitCollection { + return _prim; +} +- (UIUserInterfaceSizeClass)horizontalSizeClass +{ + return _prim.horizontalSizeClass; +} +-(UIUserInterfaceSizeClass)verticalSizeClass +{ + return _prim.verticalSizeClass; +} +- (CGFloat)displayScale +{ + return _prim.displayScale; +} +- (UIDisplayGamut)displayGamut +{ + return _prim.displayGamut; +} +- (UIForceTouchCapability)forceTouchCapability +{ + return _prim.forceTouchCapability; +} +- (UITraitEnvironmentLayoutDirection)layoutDirection +{ + return _prim.layoutDirection; +} +#if AS_BUILD_UIUSERINTERFACESTYLE +- (UIUserInterfaceStyle)userInterfaceStyle +{ + return _prim.userInterfaceStyle; +} +#endif +- (UIContentSizeCategory)preferredContentSizeCategory +{ + return _prim.preferredContentSizeCategory; +} +- (NSUInteger)hash { + return ASHashBytes(&_prim, sizeof(ASPrimitiveTraitCollection)); +} + +- (BOOL)isEqual:(id)object { + if (!object || ![object isKindOfClass:ASTraitCollection.class]) { + return NO; + } + return [self isEqualToTraitCollection:object]; +} + +- (BOOL)isEqualToTraitCollection:(ASTraitCollection *)traitCollection +{ + if (traitCollection == nil) { + return NO; + } + + if (self == traitCollection) { + return YES; + } + return ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(_prim, traitCollection->_prim); +} + +@end diff --git a/Source/Details/ASWeakProxy.m b/Source/Details/ASWeakProxy.mm similarity index 99% rename from Source/Details/ASWeakProxy.m rename to Source/Details/ASWeakProxy.mm index cfcb1aca5c..4a73408dd5 100644 --- a/Source/Details/ASWeakProxy.m +++ b/Source/Details/ASWeakProxy.mm @@ -1,5 +1,5 @@ // -// ASWeakProxy.m +// ASWeakProxy.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/ASWeakSet.m b/Source/Details/ASWeakSet.mm similarity index 99% rename from Source/Details/ASWeakSet.m rename to Source/Details/ASWeakSet.mm index 7d05dbed6e..6530271a5a 100644 --- a/Source/Details/ASWeakSet.m +++ b/Source/Details/ASWeakSet.mm @@ -1,5 +1,5 @@ // -// ASWeakSet.m +// ASWeakSet.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/CoreGraphics+ASConvenience.m b/Source/Details/CoreGraphics+ASConvenience.m deleted file mode 100644 index 0f78cf1bee..0000000000 --- a/Source/Details/CoreGraphics+ASConvenience.m +++ /dev/null @@ -1,11 +0,0 @@ -// -// CoreGraphics+ASConvenience.m -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - diff --git a/Source/Details/NSIndexSet+ASHelpers.m b/Source/Details/NSIndexSet+ASHelpers.mm similarity index 98% rename from Source/Details/NSIndexSet+ASHelpers.m rename to Source/Details/NSIndexSet+ASHelpers.mm index c38cb4c1b5..0eba0358f4 100644 --- a/Source/Details/NSIndexSet+ASHelpers.m +++ b/Source/Details/NSIndexSet+ASHelpers.mm @@ -1,5 +1,5 @@ // -// NSIndexSet+ASHelpers.m +// NSIndexSet+ASHelpers.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/NSMutableAttributedString+TextKitAdditions.m b/Source/Details/NSMutableAttributedString+TextKitAdditions.mm similarity index 96% rename from Source/Details/NSMutableAttributedString+TextKitAdditions.m rename to Source/Details/NSMutableAttributedString+TextKitAdditions.mm index 85c59b2af4..3f2ed9d35c 100644 --- a/Source/Details/NSMutableAttributedString+TextKitAdditions.m +++ b/Source/Details/NSMutableAttributedString+TextKitAdditions.mm @@ -1,5 +1,5 @@ // -// NSMutableAttributedString+TextKitAdditions.m +// NSMutableAttributedString+TextKitAdditions.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/Transactions/_ASAsyncTransactionContainer.m b/Source/Details/Transactions/_ASAsyncTransactionContainer.mm similarity index 99% rename from Source/Details/Transactions/_ASAsyncTransactionContainer.m rename to Source/Details/Transactions/_ASAsyncTransactionContainer.mm index 4a77b06705..ed44231ce2 100644 --- a/Source/Details/Transactions/_ASAsyncTransactionContainer.m +++ b/Source/Details/Transactions/_ASAsyncTransactionContainer.mm @@ -1,5 +1,5 @@ // -// _ASAsyncTransactionContainer.m +// _ASAsyncTransactionContainer.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/Transactions/_ASAsyncTransactionGroup.m b/Source/Details/Transactions/_ASAsyncTransactionGroup.mm similarity index 99% rename from Source/Details/Transactions/_ASAsyncTransactionGroup.m rename to Source/Details/Transactions/_ASAsyncTransactionGroup.mm index f9b1b9e017..ae651d1870 100644 --- a/Source/Details/Transactions/_ASAsyncTransactionGroup.m +++ b/Source/Details/Transactions/_ASAsyncTransactionGroup.mm @@ -1,5 +1,5 @@ // -// _ASAsyncTransactionGroup.m +// _ASAsyncTransactionGroup.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/UICollectionViewLayout+ASConvenience.m b/Source/Details/UICollectionViewLayout+ASConvenience.mm similarity index 95% rename from Source/Details/UICollectionViewLayout+ASConvenience.m rename to Source/Details/UICollectionViewLayout+ASConvenience.mm index dfbba66693..d63b51a157 100644 --- a/Source/Details/UICollectionViewLayout+ASConvenience.m +++ b/Source/Details/UICollectionViewLayout+ASConvenience.mm @@ -1,5 +1,5 @@ // -// UICollectionViewLayout+ASConvenience.m +// UICollectionViewLayout+ASConvenience.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Details/_ASCollectionReusableView.m b/Source/Details/_ASCollectionReusableView.mm similarity index 96% rename from Source/Details/_ASCollectionReusableView.m rename to Source/Details/_ASCollectionReusableView.mm index c104b8bea6..6f5445654f 100644 --- a/Source/Details/_ASCollectionReusableView.m +++ b/Source/Details/_ASCollectionReusableView.mm @@ -1,5 +1,5 @@ // -// _ASCollectionReusableView.m +// _ASCollectionReusableView.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -9,7 +9,8 @@ #ifndef MINIMAL_ASDK -#import "_ASCollectionReusableView.h" +#import + #import #import diff --git a/Source/Details/_ASCollectionViewCell.m b/Source/Details/_ASCollectionViewCell.mm similarity index 97% rename from Source/Details/_ASCollectionViewCell.m rename to Source/Details/_ASCollectionViewCell.mm index 6d1f7d6358..b45ab4af03 100644 --- a/Source/Details/_ASCollectionViewCell.m +++ b/Source/Details/_ASCollectionViewCell.mm @@ -1,5 +1,5 @@ // -// _ASCollectionViewCell.m +// _ASCollectionViewCell.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -8,7 +8,8 @@ // #ifndef MINIMAL_ASDK -#import "_ASCollectionViewCell.h" +#import + #import #import #import diff --git a/Source/Details/_ASDisplayViewAccessiblity.mm b/Source/Details/_ASDisplayViewAccessiblity.mm index 284eacb3ae..21ed153546 100644 --- a/Source/Details/_ASDisplayViewAccessiblity.mm +++ b/Source/Details/_ASDisplayViewAccessiblity.mm @@ -131,7 +131,7 @@ static void CollectUIAccessibilityElementsForNode(ASDisplayNode *node, ASDisplay }); } -static void CollectAccessibilityElementsForContainer(ASDisplayNode *container, _ASDisplayView *view, NSMutableArray *elements) { +static void CollectAccessibilityElementsForContainer(ASDisplayNode *container, UIView *view, NSMutableArray *elements) { UIAccessibilityElement *accessiblityElement = [ASAccessibilityElement accessibilityElementWithContainer:view node:container containerNode:container]; NSMutableArray *labeledNodes = [[NSMutableArray alloc] init]; @@ -139,7 +139,14 @@ static void CollectAccessibilityElementsForContainer(ASDisplayNode *container, _ std::queue queue; queue.push(container); - ASDisplayNode *node; + // If the container does not have an accessibility label set, or if the label is meant for custom + // actions only, then aggregate its subnodes' labels. Otherwise, treat the label as an overriden + // value and do not perform the aggregation. + BOOL shouldAggregateSubnodeLabels = + (container.accessibilityLabel.length == 0) || + (container.accessibilityTraits & InteractiveAccessibilityTraitsMask()); + + ASDisplayNode *node = nil; while (!queue.empty()) { node = queue.front(); queue.pop(); @@ -156,7 +163,7 @@ static void CollectAccessibilityElementsForContainer(ASDisplayNode *container, _ action.containerNode = node.supernode; action.container = node.supernode.view; [actions addObject:action]; - } else { + } else if (node == container || shouldAggregateSubnodeLabels) { // Even though not surfaced to UIKit, create a non-interactive element for purposes of building sorted aggregated label. ASAccessibilityElement *nonInteractiveElement = [ASAccessibilityElement accessibilityElementWithContainer:view node:node containerNode:container]; [labeledNodes addObject:nonInteractiveElement]; @@ -195,7 +202,7 @@ static void CollectAccessibilityElementsForContainer(ASDisplayNode *container, _ } /// Collect all accessibliity elements for a given view and view node -static void CollectAccessibilityElementsForView(_ASDisplayView *view, NSMutableArray *elements) +static void CollectAccessibilityElementsForView(UIView *view, NSMutableArray *elements) { ASDisplayNodeCAssertNotNil(elements, @"Should pass in a NSMutableArray"); @@ -258,17 +265,28 @@ static void CollectAccessibilityElementsForView(_ASDisplayView *view, NSMutableA if (viewNode == nil) { return @[]; } - if (_accessibilityElements == nil) { - NSMutableArray *accessibilityElements = [[NSMutableArray alloc] init]; - CollectAccessibilityElementsForView(self, accessibilityElements); - SortAccessibilityElements(accessibilityElements); - _accessibilityElements = accessibilityElements; + _accessibilityElements = [viewNode accessibilityElements]; } - return _accessibilityElements; } @end +@implementation ASDisplayNode (AccessibilityInternal) + +- (NSArray *)accessibilityElements +{ + if (!self.isNodeLoaded) { + ASDisplayNodeFailAssert(@"Cannot access accessibilityElements since node is not loaded"); + return @[]; + } + NSMutableArray *accessibilityElements = [[NSMutableArray alloc] init]; + CollectAccessibilityElementsForView(self.view, accessibilityElements); + SortAccessibilityElements(accessibilityElements); + return accessibilityElements; +} + +@end + #endif diff --git a/Source/IGListAdapter+AsyncDisplayKit.m b/Source/IGListAdapter+AsyncDisplayKit.mm similarity index 89% rename from Source/IGListAdapter+AsyncDisplayKit.m rename to Source/IGListAdapter+AsyncDisplayKit.mm index 757a96d560..ec085da68e 100644 --- a/Source/IGListAdapter+AsyncDisplayKit.m +++ b/Source/IGListAdapter+AsyncDisplayKit.mm @@ -1,5 +1,5 @@ // -// IGListAdapter+AsyncDisplayKit.m +// IGListAdapter+AsyncDisplayKit.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -11,9 +11,9 @@ #if AS_IG_LIST_KIT -#import "IGListAdapter+AsyncDisplayKit.h" -#import "ASIGListAdapterBasedDataSource.h" -#import "ASAssert.h" +#import +#import +#import #import @implementation IGListAdapter (AsyncDisplayKit) diff --git a/Source/Layout/ASAsciiArtBoxCreator.m b/Source/Layout/ASAsciiArtBoxCreator.mm similarity index 99% rename from Source/Layout/ASAsciiArtBoxCreator.m rename to Source/Layout/ASAsciiArtBoxCreator.mm index 5b2488648e..78eb572ead 100644 --- a/Source/Layout/ASAsciiArtBoxCreator.m +++ b/Source/Layout/ASAsciiArtBoxCreator.mm @@ -1,5 +1,5 @@ // -// ASAsciiArtBoxCreator.m +// ASAsciiArtBoxCreator.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -10,7 +10,7 @@ #import #import -#import +#import static const NSUInteger kDebugBoxPadding = 2; diff --git a/Source/Layout/ASLayoutElement.mm b/Source/Layout/ASLayoutElement.mm index a89ed11a8d..add4964759 100644 --- a/Source/Layout/ASLayoutElement.mm +++ b/Source/Layout/ASLayoutElement.mm @@ -156,7 +156,7 @@ do {\ @implementation ASLayoutElementStyle { ASDN::RecursiveMutex __instanceLock__; ASLayoutElementStyleExtensions _extensions; - + std::atomic _size; std::atomic _spacingBefore; std::atomic _spacingAfter; @@ -181,6 +181,7 @@ do {\ std::atomic _padding; std::atomic _border; std::atomic _aspectRatio; + ASStackLayoutAlignItems _parentAlignStyle; #endif } @@ -203,6 +204,9 @@ do {\ self = [super init]; if (self) { _size = ASLayoutElementSizeMake(); +#if YOGA + _parentAlignStyle = ASStackLayoutAlignItemsNotSet; +#endif } return self; } @@ -778,6 +782,10 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__) - (ASEdgeInsets)padding { return _padding.load(); } - (ASEdgeInsets)border { return _border.load(); } - (CGFloat)aspectRatio { return _aspectRatio.load(); } +// private (ASLayoutElementStylePrivate.h) +- (ASStackLayoutAlignItems)parentAlignStyle { + return _parentAlignStyle; +} - (void)setFlexWrap:(YGWrap)flexWrap { _flexWrap.store(flexWrap); @@ -823,6 +831,10 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__) _aspectRatio.store(aspectRatio); ASLayoutElementStyleCallDelegate(ASYogaAspectRatioProperty); } +// private (ASLayoutElementStylePrivate.h) +- (void)setParentAlignStyle:(ASStackLayoutAlignItems)style { + _parentAlignStyle = style; +} #endif /* YOGA */ diff --git a/Source/Layout/ASYogaUtilities.h b/Source/Layout/ASYogaUtilities.h index cad80ecb0f..c3d1d8233c 100644 --- a/Source/Layout/ASYogaUtilities.h +++ b/Source/Layout/ASYogaUtilities.h @@ -26,6 +26,7 @@ @end +// pre-order, depth-first AS_EXTERN void ASDisplayNodePerformBlockOnEveryYogaChild(ASDisplayNode *node, void(^block)(ASDisplayNode *node)); #pragma mark - Yoga Type Conversion Helpers @@ -40,9 +41,10 @@ AS_EXTERN float yogaDimensionToPercent(ASDimension dimension); AS_EXTERN ASDimension dimensionForEdgeWithEdgeInsets(YGEdge edge, ASEdgeInsets insets); AS_EXTERN void ASLayoutElementYogaUpdateMeasureFunc(YGNodeRef yogaNode, id layoutElement); +AS_EXTERN float ASLayoutElementYogaBaselineFunc(YGNodeRef yogaNode, const float width, const float height); AS_EXTERN YGSize ASLayoutElementYogaMeasureFunc(YGNodeRef yogaNode, - float width, YGMeasureMode widthMode, - float height, YGMeasureMode heightMode); + float width, YGMeasureMode widthMode, + float height, YGMeasureMode heightMode); #pragma mark - Yoga Style Setter Helpers diff --git a/Source/Layout/ASYogaUtilities.mm b/Source/Layout/ASYogaUtilities.mm index 2cca2307c3..fa6e135920 100644 --- a/Source/Layout/ASYogaUtilities.mm +++ b/Source/Layout/ASYogaUtilities.mm @@ -7,7 +7,7 @@ // #import - +#import #if YOGA /* YOGA */ @implementation ASDisplayNode (YogaHelpers) @@ -143,23 +143,51 @@ void ASLayoutElementYogaUpdateMeasureFunc(YGNodeRef yogaNode, id element = (__bridge_transfer id)YGNodeGetContext(yogaNode); + __unused id element = (__bridge_transfer id)YGNodeGetContext(yogaNode); YGNodeSetContext(yogaNode, NULL); YGNodeSetMeasureFunc(yogaNode, NULL); + YGNodeSetBaselineFunc(yogaNode, NULL); + } +} + +float ASLayoutElementYogaBaselineFunc(YGNodeRef yogaNode, const float width, const float height) +{ + id layoutElement = (__bridge id)YGNodeGetContext(yogaNode); + ASDisplayNodeCAssert([layoutElement conformsToProtocol:@protocol(ASLayoutElement)], + @"Yoga context must be "); + + ASDisplayNode *displayNode = ASDynamicCast(layoutElement, ASDisplayNode); + + switch (displayNode.style.parentAlignStyle) { + case ASStackLayoutAlignItemsBaselineFirst: + return layoutElement.style.ascender; + case ASStackLayoutAlignItemsBaselineLast: + return height + layoutElement.style.descender; + default: + return 0; } } diff --git a/Source/Private/ASAbstractLayoutController+FrameworkPrivate.h b/Source/Private/ASAbstractLayoutController+FrameworkPrivate.h new file mode 100644 index 0000000000..f836fa0b84 --- /dev/null +++ b/Source/Private/ASAbstractLayoutController+FrameworkPrivate.h @@ -0,0 +1,21 @@ +// +// ASAbstractLayoutController+FrameworkPrivate.h +// Texture +// +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +// +// The following methods are ONLY for use by _ASDisplayLayer, _ASDisplayView, and ASDisplayNode. +// These methods must never be called or overridden by other classes. +// + +#include + +@interface ASAbstractLayoutController (FrameworkPrivate) + ++ (std::vector>)defaultTuningParameters; + +@end diff --git a/Source/Private/ASBatchFetching.m b/Source/Private/ASBatchFetching.mm similarity index 99% rename from Source/Private/ASBatchFetching.m rename to Source/Private/ASBatchFetching.mm index ee39e6d4e6..44b31ed77d 100644 --- a/Source/Private/ASBatchFetching.m +++ b/Source/Private/ASBatchFetching.mm @@ -1,5 +1,5 @@ // -// ASBatchFetching.m +// ASBatchFetching.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASCollectionLayoutDefines.m b/Source/Private/ASCollectionLayoutDefines.mm similarity index 95% rename from Source/Private/ASCollectionLayoutDefines.m rename to Source/Private/ASCollectionLayoutDefines.mm index 0087af536a..e386575c5d 100644 --- a/Source/Private/ASCollectionLayoutDefines.m +++ b/Source/Private/ASCollectionLayoutDefines.mm @@ -1,5 +1,5 @@ // -// ASCollectionLayoutDefines.m +// ASCollectionLayoutDefines.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Private/ASCollectionViewFlowLayoutInspector.m b/Source/Private/ASCollectionViewFlowLayoutInspector.mm similarity index 99% rename from Source/Private/ASCollectionViewFlowLayoutInspector.m rename to Source/Private/ASCollectionViewFlowLayoutInspector.mm index 79230de4cb..6dc9d73bfb 100644 --- a/Source/Private/ASCollectionViewFlowLayoutInspector.m +++ b/Source/Private/ASCollectionViewFlowLayoutInspector.mm @@ -1,5 +1,5 @@ // -// ASCollectionViewFlowLayoutInspector.m +// ASCollectionViewFlowLayoutInspector.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASControlTargetAction.m b/Source/Private/ASControlTargetAction.mm similarity index 97% rename from Source/Private/ASControlTargetAction.m rename to Source/Private/ASControlTargetAction.mm index ea822db2fc..41cc113314 100644 --- a/Source/Private/ASControlTargetAction.m +++ b/Source/Private/ASControlTargetAction.mm @@ -1,5 +1,5 @@ // -// ASControlTargetAction.m +// ASControlTargetAction.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASDefaultPlayButton.m b/Source/Private/ASDefaultPlayButton.mm similarity index 98% rename from Source/Private/ASDefaultPlayButton.m rename to Source/Private/ASDefaultPlayButton.mm index 133db9a7e2..589bda90c2 100644 --- a/Source/Private/ASDefaultPlayButton.m +++ b/Source/Private/ASDefaultPlayButton.mm @@ -1,5 +1,5 @@ // -// ASDefaultPlayButton.m +// ASDefaultPlayButton.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASDefaultPlaybackButton.m b/Source/Private/ASDefaultPlaybackButton.mm similarity index 98% rename from Source/Private/ASDefaultPlaybackButton.m rename to Source/Private/ASDefaultPlaybackButton.mm index ecc276069c..deda7e8716 100644 --- a/Source/Private/ASDefaultPlaybackButton.m +++ b/Source/Private/ASDefaultPlaybackButton.mm @@ -1,5 +1,5 @@ // -// ASDefaultPlaybackButton.m +// ASDefaultPlaybackButton.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASDispatch.m b/Source/Private/ASDispatch.mm similarity index 94% rename from Source/Private/ASDispatch.m rename to Source/Private/ASDispatch.mm index f73281dfda..5c713db802 100644 --- a/Source/Private/ASDispatch.m +++ b/Source/Private/ASDispatch.mm @@ -1,5 +1,5 @@ // -// ASDispatch.m +// ASDispatch.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. @@ -7,6 +7,8 @@ // #import + +// Prefer C atomics in this file because ObjC blocks can't capture C++ atomics well. #import /** diff --git a/Source/Private/ASDisplayNode+FrameworkPrivate.h b/Source/Private/ASDisplayNode+FrameworkPrivate.h index 2101565bf3..c8d5476b3a 100644 --- a/Source/Private/ASDisplayNode+FrameworkPrivate.h +++ b/Source/Private/ASDisplayNode+FrameworkPrivate.h @@ -312,6 +312,10 @@ __unused static NSString * _Nonnull NSStringFromASHierarchyStateChange(ASHierarc @end +@interface ASDisplayNode (AccessibilityInternal) +- (NSArray *)accessibilityElements; +@end; + @interface UIView (ASDisplayNodeInternal) @property (nullable, weak) ASDisplayNode *asyncdisplaykit_node; @end diff --git a/Source/Private/ASDisplayNodeCornerLayerDelegate.m b/Source/Private/ASDisplayNodeCornerLayerDelegate.mm similarity index 91% rename from Source/Private/ASDisplayNodeCornerLayerDelegate.m rename to Source/Private/ASDisplayNodeCornerLayerDelegate.mm index 8973570224..42838baba1 100644 --- a/Source/Private/ASDisplayNodeCornerLayerDelegate.m +++ b/Source/Private/ASDisplayNodeCornerLayerDelegate.mm @@ -1,5 +1,5 @@ // -// ASDisplayNodeCornerLayerDelegate.m +// ASDisplayNodeCornerLayerDelegate.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASDisplayNodeInternal.h b/Source/Private/ASDisplayNodeInternal.h index 5f9092ffaa..1e907d3e7f 100644 --- a/Source/Private/ASDisplayNodeInternal.h +++ b/Source/Private/ASDisplayNodeInternal.h @@ -386,4 +386,13 @@ AS_EXTERN NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimest @end +@interface ASDisplayNode (ASLayoutElementPrivate) + +/** + * Returns the internal style object or creates a new if no exists. Need to be called with lock held. + */ +- (ASLayoutElementStyle *)_locked_style; + +@end + NS_ASSUME_NONNULL_END diff --git a/Source/Private/ASDisplayNodeTipState.m b/Source/Private/ASDisplayNodeTipState.mm similarity index 94% rename from Source/Private/ASDisplayNodeTipState.m rename to Source/Private/ASDisplayNodeTipState.mm index 8050d27346..b5a4231998 100644 --- a/Source/Private/ASDisplayNodeTipState.m +++ b/Source/Private/ASDisplayNodeTipState.mm @@ -1,5 +1,5 @@ // -// ASDisplayNodeTipState.m +// ASDisplayNodeTipState.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASIGListAdapterBasedDataSource.m b/Source/Private/ASIGListAdapterBasedDataSource.mm similarity index 99% rename from Source/Private/ASIGListAdapterBasedDataSource.m rename to Source/Private/ASIGListAdapterBasedDataSource.mm index a489acf950..1bbf65c895 100644 --- a/Source/Private/ASIGListAdapterBasedDataSource.m +++ b/Source/Private/ASIGListAdapterBasedDataSource.mm @@ -1,5 +1,5 @@ // -// ASIGListAdapterBasedDataSource.m +// ASIGListAdapterBasedDataSource.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASImageNode+CGExtras.m b/Source/Private/ASImageNode+CGExtras.mm similarity index 99% rename from Source/Private/ASImageNode+CGExtras.m rename to Source/Private/ASImageNode+CGExtras.mm index acbd6857e1..c4f9fdcbc9 100644 --- a/Source/Private/ASImageNode+CGExtras.m +++ b/Source/Private/ASImageNode+CGExtras.mm @@ -1,5 +1,5 @@ // -// ASImageNode+CGExtras.m +// ASImageNode+CGExtras.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -9,7 +9,7 @@ #import -#import +#import // TODO rewrite these to be closer to the intended use -- take UIViewContentMode as param, CGRect destinationBounds, CGSize sourceSize. static CGSize _ASSizeFillWithAspectRatio(CGFloat aspectRatio, CGSize constraints); diff --git a/Source/Private/ASInternalHelpers.m b/Source/Private/ASInternalHelpers.mm similarity index 90% rename from Source/Private/ASInternalHelpers.m rename to Source/Private/ASInternalHelpers.mm index 484560aa89..a9926ccca4 100644 --- a/Source/Private/ASInternalHelpers.m +++ b/Source/Private/ASInternalHelpers.mm @@ -1,5 +1,5 @@ // -// ASInternalHelpers.m +// ASInternalHelpers.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -12,7 +12,7 @@ #import #import -#import +#import #import #import @@ -45,16 +45,19 @@ BOOL ASDefaultAllowsEdgeAntialiasing() void ASInitializeFrameworkMainThread(void) { - ASDisplayNodeCAssertMainThread(); - // Ensure these values are cached on the main thread before needed in the background. - if (ASActivateExperimentalFeature(ASExperimentalLayerDefaults)) { - // Nop. We will gather default values on-demand in ASDefaultAllowsGroupOpacity and ASDefaultAllowsEdgeAntialiasing - } else { - CALayer *layer = [[[UIView alloc] init] layer]; - allowsGroupOpacityFromUIKitOrNil = @(layer.allowsGroupOpacity); - allowsEdgeAntialiasingFromUIKitOrNil = @(layer.allowsEdgeAntialiasing); - } - ASNotifyInitialized(); + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + ASDisplayNodeCAssertMainThread(); + // Ensure these values are cached on the main thread before needed in the background. + if (ASActivateExperimentalFeature(ASExperimentalLayerDefaults)) { + // Nop. We will gather default values on-demand in ASDefaultAllowsGroupOpacity and ASDefaultAllowsEdgeAntialiasing + } else { + CALayer *layer = [[[UIView alloc] init] layer]; + allowsGroupOpacityFromUIKitOrNil = @(layer.allowsGroupOpacity); + allowsEdgeAntialiasingFromUIKitOrNil = @(layer.allowsEdgeAntialiasing); + } + ASNotifyInitialized(); + }); } BOOL ASSubclassOverridesSelector(Class superclass, Class subclass, SEL selector) diff --git a/Source/Private/ASLayerBackingTipProvider.m b/Source/Private/ASLayerBackingTipProvider.mm similarity index 97% rename from Source/Private/ASLayerBackingTipProvider.m rename to Source/Private/ASLayerBackingTipProvider.mm index 9a5932faa8..19d1850ab7 100644 --- a/Source/Private/ASLayerBackingTipProvider.m +++ b/Source/Private/ASLayerBackingTipProvider.mm @@ -1,5 +1,5 @@ // -// ASLayerBackingTipProvider.m +// ASLayerBackingTipProvider.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASLayoutTransition.mm b/Source/Private/ASLayoutTransition.mm index 1e482afa63..b7d9cda441 100644 --- a/Source/Private/ASLayoutTransition.mm +++ b/Source/Private/ASLayoutTransition.mm @@ -81,7 +81,7 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) { - (BOOL)isSynchronous { - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); return !ASLayoutCanTransitionAsynchronous(_pendingLayout.layout); } @@ -93,7 +93,7 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) { - (void)applySubnodeInsertionsAndMoves { - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); [self calculateSubnodeOperationsIfNeeded]; // Create an activity even if no subnodes affected. @@ -131,7 +131,7 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) { - (void)applySubnodeRemovals { as_activity_scope(as_activity_create("Apply subnode removals", AS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT)); - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); [self calculateSubnodeOperationsIfNeeded]; if (_removedSubnodes.count == 0) { @@ -151,7 +151,7 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) { - (void)calculateSubnodeOperationsIfNeeded { - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); if (_calculatedSubnodeOperations) { return; } @@ -206,27 +206,27 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) { - (NSArray *)currentSubnodesWithTransitionContext:(_ASTransitionContext *)context { - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); return _node.subnodes; } - (NSArray *)insertedSubnodesWithTransitionContext:(_ASTransitionContext *)context { - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); [self calculateSubnodeOperationsIfNeeded]; return _insertedSubnodes; } - (NSArray *)removedSubnodesWithTransitionContext:(_ASTransitionContext *)context { - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); [self calculateSubnodeOperationsIfNeeded]; return _removedSubnodes; } - (ASLayout *)transitionContext:(_ASTransitionContext *)context layoutForKey:(NSString *)key { - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); if ([key isEqualToString:ASTransitionContextFromLayoutKey]) { return _previousLayout.layout; } else if ([key isEqualToString:ASTransitionContextToLayoutKey]) { @@ -238,7 +238,7 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) { - (ASSizeRange)transitionContext:(_ASTransitionContext *)context constrainedSizeForKey:(NSString *)key { - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); if ([key isEqualToString:ASTransitionContextFromLayoutKey]) { return _previousLayout.constrainedSize; } else if ([key isEqualToString:ASTransitionContextToLayoutKey]) { diff --git a/Source/Private/ASMutableElementMap.m b/Source/Private/ASMutableElementMap.mm similarity index 98% rename from Source/Private/ASMutableElementMap.m rename to Source/Private/ASMutableElementMap.mm index 1e2e203a21..32d45b1f0a 100644 --- a/Source/Private/ASMutableElementMap.m +++ b/Source/Private/ASMutableElementMap.mm @@ -1,5 +1,5 @@ // -// ASMutableElementMap.m +// ASMutableElementMap.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -9,7 +9,7 @@ #ifndef MINIMAL_ASDK -#import "ASMutableElementMap.h" +#import #import #import diff --git a/Source/Private/ASResponderChainEnumerator.m b/Source/Private/ASResponderChainEnumerator.mm similarity index 91% rename from Source/Private/ASResponderChainEnumerator.m rename to Source/Private/ASResponderChainEnumerator.mm index a127c64c1e..bb16e0fc57 100644 --- a/Source/Private/ASResponderChainEnumerator.m +++ b/Source/Private/ASResponderChainEnumerator.mm @@ -1,5 +1,5 @@ // -// ASResponderChainEnumerator.m +// ASResponderChainEnumerator.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import "ASResponderChainEnumerator.h" +#import #import @implementation ASResponderChainEnumerator { diff --git a/Source/Private/ASSection.m b/Source/Private/ASSection.mm similarity index 97% rename from Source/Private/ASSection.m rename to Source/Private/ASSection.mm index 77e53df71d..a151774bd4 100644 --- a/Source/Private/ASSection.m +++ b/Source/Private/ASSection.mm @@ -1,5 +1,5 @@ // -// ASSection.m +// ASSection.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASTip.m b/Source/Private/ASTip.mm similarity index 94% rename from Source/Private/ASTip.m rename to Source/Private/ASTip.mm index fde1bbc587..af1d299221 100644 --- a/Source/Private/ASTip.m +++ b/Source/Private/ASTip.mm @@ -1,5 +1,5 @@ // -// ASTip.m +// ASTip.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import "ASTip.h" +#import #if AS_ENABLE_TIPS diff --git a/Source/Private/ASTipNode.m b/Source/Private/ASTipNode.mm similarity index 97% rename from Source/Private/ASTipNode.m rename to Source/Private/ASTipNode.mm index a4fe4bf4e5..dcca908b8a 100644 --- a/Source/Private/ASTipNode.m +++ b/Source/Private/ASTipNode.mm @@ -1,5 +1,5 @@ // -// ASTipNode.m +// ASTipNode.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASTipProvider.m b/Source/Private/ASTipProvider.mm similarity index 93% rename from Source/Private/ASTipProvider.m rename to Source/Private/ASTipProvider.mm index 7787997376..237e83cda0 100644 --- a/Source/Private/ASTipProvider.m +++ b/Source/Private/ASTipProvider.mm @@ -1,5 +1,5 @@ // -// ASTipProvider.m +// ASTipProvider.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import "ASTipProvider.h" +#import #if AS_ENABLE_TIPS diff --git a/Source/Private/ASTipsController.m b/Source/Private/ASTipsController.mm similarity index 98% rename from Source/Private/ASTipsController.m rename to Source/Private/ASTipsController.mm index d12b3189bf..acc592130c 100644 --- a/Source/Private/ASTipsController.m +++ b/Source/Private/ASTipsController.mm @@ -1,5 +1,5 @@ // -// ASTipsController.m +// ASTipsController.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import "ASTipsController.h" +#import #if AS_ENABLE_TIPS diff --git a/Source/Private/ASTipsWindow.m b/Source/Private/ASTipsWindow.mm similarity index 97% rename from Source/Private/ASTipsWindow.m rename to Source/Private/ASTipsWindow.mm index a330fc7d59..010932613a 100644 --- a/Source/Private/ASTipsWindow.m +++ b/Source/Private/ASTipsWindow.mm @@ -1,5 +1,5 @@ // -// ASTipsWindow.m +// ASTipsWindow.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import "ASTipsWindow.h" +#import #if AS_ENABLE_TIPS #import diff --git a/Source/Private/ASTwoDimensionalArrayUtils.m b/Source/Private/ASTwoDimensionalArrayUtils.mm similarity index 99% rename from Source/Private/ASTwoDimensionalArrayUtils.m rename to Source/Private/ASTwoDimensionalArrayUtils.mm index c9c2b658d8..8b4836fe89 100644 --- a/Source/Private/ASTwoDimensionalArrayUtils.m +++ b/Source/Private/ASTwoDimensionalArrayUtils.mm @@ -1,5 +1,5 @@ // -// ASTwoDimensionalArrayUtils.m +// ASTwoDimensionalArrayUtils.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/ASWeakMap.m b/Source/Private/ASWeakMap.mm similarity index 99% rename from Source/Private/ASWeakMap.m rename to Source/Private/ASWeakMap.mm index 42f192f9c6..3110b13d37 100644 --- a/Source/Private/ASWeakMap.m +++ b/Source/Private/ASWeakMap.mm @@ -1,5 +1,5 @@ // -// ASWeakMap.m +// ASWeakMap.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/Layout/ASLayoutElementStylePrivate.h b/Source/Private/Layout/ASLayoutElementStylePrivate.h index 375be772e9..69e29824ef 100644 --- a/Source/Private/Layout/ASLayoutElementStylePrivate.h +++ b/Source/Private/Layout/ASLayoutElementStylePrivate.h @@ -9,6 +9,7 @@ #pragma once +#import #import @interface ASLayoutElementStyle () @@ -25,4 +26,6 @@ */ @property (nonatomic, readonly) ASLayoutElementSize size; +@property (nonatomic, assign) ASStackLayoutAlignItems parentAlignStyle; + @end diff --git a/Source/Private/TextExperiment/Component/ASTextDebugOption.m b/Source/Private/TextExperiment/Component/ASTextDebugOption.mm similarity index 99% rename from Source/Private/TextExperiment/Component/ASTextDebugOption.m rename to Source/Private/TextExperiment/Component/ASTextDebugOption.mm index 6b74b0990b..2565b903c9 100644 --- a/Source/Private/TextExperiment/Component/ASTextDebugOption.m +++ b/Source/Private/TextExperiment/Component/ASTextDebugOption.mm @@ -1,5 +1,5 @@ // -// ASTextDebugOption.m +// ASTextDebugOption.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Private/TextExperiment/Component/ASTextInput.m b/Source/Private/TextExperiment/Component/ASTextInput.mm similarity index 99% rename from Source/Private/TextExperiment/Component/ASTextInput.m rename to Source/Private/TextExperiment/Component/ASTextInput.mm index 07bc6cb6d5..1cdfe73858 100644 --- a/Source/Private/TextExperiment/Component/ASTextInput.m +++ b/Source/Private/TextExperiment/Component/ASTextInput.mm @@ -1,5 +1,5 @@ // -// ASTextInput.m +// ASTextInput.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/TextExperiment/Component/ASTextLayout.m b/Source/Private/TextExperiment/Component/ASTextLayout.mm similarity index 93% rename from Source/Private/TextExperiment/Component/ASTextLayout.m rename to Source/Private/TextExperiment/Component/ASTextLayout.mm index 5c0b0cda53..ec029d62e5 100644 --- a/Source/Private/TextExperiment/Component/ASTextLayout.m +++ b/Source/Private/TextExperiment/Component/ASTextLayout.mm @@ -1,5 +1,5 @@ // -// ASTextLayout.m +// ASTextLayout.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -102,6 +102,13 @@ static CGColorRef ASTextGetCGColor(CGColorRef color) { id _linePositionModifier; } +- (NSString *)description +{ + return [NSString + stringWithFormat:@"immutable: %@, insets: %@, size: %@", self->_readonly ? @"YES" : @"NO", + NSStringFromUIEdgeInsets(self->_insets), NSStringFromCGSize(self->_size)]; +} + + (instancetype)containerWithSize:(CGSize)size NS_RETURNS_RETAINED { return [self containerWithSize:size insets:UIEdgeInsetsZero]; } @@ -373,6 +380,14 @@ dispatch_semaphore_signal(_lock); return self; } +- (NSString *)description +{ + return [NSString stringWithFormat:@"lines: %ld, visibleRange:%@, textBoundingRect:%@", + [self.lines count], + NSStringFromRange(self.visibleRange), + NSStringFromCGRect(self.textBoundingRect)]; +} + + (ASTextLayout *)layoutWithContainerSize:(CGSize)size text:(NSAttributedString *)text { ASTextContainer *container = [ASTextContainer containerWithSize:size]; return [self layoutWithContainer:container text:text]; @@ -426,7 +441,7 @@ dispatch_semaphore_signal(_lock); // It may use larger constraint size when create CTFrame with // CTFramesetterCreateFrame in iOS 10. BOOL needFixLayoutSizeBug = AS_AT_LEAST_IOS10; - + layout = [[ASTextLayout alloc] _init]; layout.text = text; layout.container = container; @@ -584,6 +599,7 @@ dispatch_semaphore_signal(_lock); // calculate line frame NSUInteger lineCurrentIdx = 0; + BOOL measuringBeyondConstraints = NO; for (NSUInteger i = 0; i < lineCount; i++) { CTLineRef ctLine = (CTLineRef)CFArrayGetValueAtIndex(ctLines, i); CFArrayRef ctRuns = CTLineGetGlyphRuns(ctLine); @@ -598,22 +614,35 @@ dispatch_semaphore_signal(_lock); position.y = cgPathBox.size.height + cgPathBox.origin.y - ctLineOrigin.y; ASTextLine *line = [ASTextLine lineWithCTLine:ctLine position:position vertical:isVerticalForm]; - CGRect rect = line.bounds; + [lines addObject:line]; + } + + // Give user a chance to modify the line's position. + [container.linePositionModifier modifyLines:lines fromText:text inContainer:container]; + + BOOL first = YES; + for (ASTextLine *line in lines) { + CGPoint position = line.position; + CGRect rect = line.bounds; if (constraintSizeIsExtended) { if (isVerticalForm) { if (rect.origin.x + rect.size.width > constraintRectBeforeExtended.origin.x + - constraintRectBeforeExtended.size.width) break; + constraintRectBeforeExtended.size.width) { + measuringBeyondConstraints = YES; + } } else { if (rect.origin.y + rect.size.height > constraintRectBeforeExtended.origin.y + - constraintRectBeforeExtended.size.height) break; + constraintRectBeforeExtended.size.height) { + measuringBeyondConstraints = YES; + } } } - - BOOL newRow = YES; - if (rowMaySeparated && position.x != lastPosition.x) { + + BOOL newRow = !measuringBeyondConstraints; + if (newRow && rowMaySeparated && position.x != lastPosition.x) { if (isVerticalForm) { if (rect.size.width > lastRect.size.width) { if (rect.origin.x > lastPosition.x && lastPosition.x > rect.origin.x - rect.size.width) newRow = NO; @@ -635,188 +664,218 @@ dispatch_semaphore_signal(_lock); line.index = lineCurrentIdx; line.row = rowIdx; - [lines addObject:line]; + rowCount = rowIdx + 1; lineCurrentIdx ++; - - if (i == 0) textBoundingRect = rect; - else { + + if (first) { + first = NO; + textBoundingRect = rect; + } else if (!measuringBeyondConstraints) { if (maximumNumberOfRows == 0 || rowIdx < maximumNumberOfRows) { textBoundingRect = CGRectUnion(textBoundingRect, rect); } } } - - if (rowCount > 0) { - if (maximumNumberOfRows > 0) { - if (rowCount > maximumNumberOfRows) { - needTruncation = YES; - rowCount = maximumNumberOfRows; - do { - ASTextLine *line = lines.lastObject; - if (!line) break; - if (line.row < rowCount) break; - [lines removeLastObject]; - } while (1); + + { + NSMutableArray *removedLines = [NSMutableArray new]; + if (rowCount > 0) { + if (maximumNumberOfRows > 0) { + if (rowCount > maximumNumberOfRows) { + needTruncation = YES; + rowCount = maximumNumberOfRows; + do { + ASTextLine *line = lines.lastObject; + if (!line) break; + if (line.row < rowCount) break; // we have removed down to an allowed # of lines now + [lines removeLastObject]; + [removedLines addObject:line]; + } while (1); + } } - } - ASTextLine *lastLine = lines.lastObject; - if (!needTruncation && lastLine.range.location + lastLine.range.length < text.length) { - needTruncation = YES; - } - - // Give user a chance to modify the line's position. - if (container.linePositionModifier) { - [container.linePositionModifier modifyLines:lines fromText:text inContainer:container]; - textBoundingRect = CGRectZero; + ASTextLine *lastLine = rowCount < lines.count ? lines[rowCount - 1] : lines.lastObject; + if (!needTruncation && lastLine.range.location + lastLine.range.length < text.length) { + needTruncation = YES; + while (lines.count > rowCount) { + ASTextLine *line = lines.lastObject; + [lines removeLastObject]; + [removedLines addObject:line]; + } + } + + lineRowsEdge = (ASRowEdge *) calloc(rowCount, sizeof(ASRowEdge)); + if (lineRowsEdge == NULL) FAIL_AND_RETURN + lineRowsIndex = (NSUInteger *) calloc(rowCount, sizeof(NSUInteger)); + if (lineRowsIndex == NULL) FAIL_AND_RETURN + NSInteger lastRowIdx = -1; + CGFloat lastHead = 0; + CGFloat lastFoot = 0; for (NSUInteger i = 0, max = lines.count; i < max; i++) { ASTextLine *line = lines[i]; - if (i == 0) textBoundingRect = line.bounds; - else textBoundingRect = CGRectUnion(textBoundingRect, line.bounds); - } - } - - lineRowsEdge = (ASRowEdge *)calloc(rowCount, sizeof(ASRowEdge)); - if (lineRowsEdge == NULL) FAIL_AND_RETURN - lineRowsIndex = (NSUInteger *)calloc(rowCount, sizeof(NSUInteger)); - if (lineRowsIndex == NULL) FAIL_AND_RETURN - NSInteger lastRowIdx = -1; - CGFloat lastHead = 0; - CGFloat lastFoot = 0; - for (NSUInteger i = 0, max = lines.count; i < max; i++) { - ASTextLine *line = lines[i]; - CGRect rect = line.bounds; - if ((NSInteger)line.row != lastRowIdx) { - if (lastRowIdx >= 0) { - lineRowsEdge[lastRowIdx] = (ASRowEdge) {.head = lastHead, .foot = lastFoot }; - } - lastRowIdx = line.row; - lineRowsIndex[lastRowIdx] = i; - if (isVerticalForm) { - lastHead = rect.origin.x + rect.size.width; - lastFoot = lastHead - rect.size.width; - } else { - lastHead = rect.origin.y; - lastFoot = lastHead + rect.size.height; - } - } else { - if (isVerticalForm) { - lastHead = MAX(lastHead, rect.origin.x + rect.size.width); - lastFoot = MIN(lastFoot, rect.origin.x); - } else { - lastHead = MIN(lastHead, rect.origin.y); - lastFoot = MAX(lastFoot, rect.origin.y + rect.size.height); - } - } - } - lineRowsEdge[lastRowIdx] = (ASRowEdge) {.head = lastHead, .foot = lastFoot }; - - for (NSUInteger i = 1; i < rowCount; i++) { - ASRowEdge v0 = lineRowsEdge[i - 1]; - ASRowEdge v1 = lineRowsEdge[i]; - lineRowsEdge[i - 1].foot = lineRowsEdge[i].head = (v0.foot + v1.head) * 0.5; - } - } - - { // calculate bounding size - CGRect rect = textBoundingRect; - if (container.path) { - if (container.pathLineWidth > 0) { - CGFloat inset = container.pathLineWidth / 2; - rect = CGRectInset(rect, -inset, -inset); - } - } else { - rect = UIEdgeInsetsInsetRect(rect,ASTextUIEdgeInsetsInvert(container.insets)); - } - rect = CGRectStandardize(rect); - CGSize size = rect.size; - if (container.verticalForm) { - size.width += container.size.width - (rect.origin.x + rect.size.width); - } else { - size.width += rect.origin.x; - } - size.height += rect.origin.y; - if (size.width < 0) size.width = 0; - if (size.height < 0) size.height = 0; - size.width = ceil(size.width); - size.height = ceil(size.height); - textBoundingSize = size; - } - - visibleRange = ASTextNSRangeFromCFRange(CTFrameGetVisibleStringRange(ctFrame)); - if (needTruncation) { - ASTextLine *lastLine = lines.lastObject; - NSRange lastRange = lastLine.range; - visibleRange.length = lastRange.location + lastRange.length - visibleRange.location; - - // create truncated line - if (container.truncationType != ASTextTruncationTypeNone) { - CTLineRef truncationTokenLine = NULL; - if (container.truncationToken) { - truncationToken = container.truncationToken; - truncationTokenLine = CTLineCreateWithAttributedString((CFAttributedStringRef)truncationToken); - } else { - CFArrayRef runs = CTLineGetGlyphRuns(lastLine.CTLine); - NSUInteger runCount = CFArrayGetCount(runs); - NSMutableDictionary *attrs = nil; - if (runCount > 0) { - CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, runCount - 1); - attrs = (id)CTRunGetAttributes(run); - attrs = attrs ? attrs.mutableCopy : [NSMutableArray new]; - [attrs removeObjectsForKeys:[NSMutableAttributedString as_allDiscontinuousAttributeKeys]]; - CTFontRef font = (__bridge CTFontRef)attrs[(id)kCTFontAttributeName]; - CGFloat fontSize = font ? CTFontGetSize(font) : 12.0; - UIFont *uiFont = [UIFont systemFontOfSize:fontSize * 0.9]; - if (uiFont) { - font = CTFontCreateWithName((__bridge CFStringRef)uiFont.fontName, uiFont.pointSize, NULL); + CGRect rect = line.bounds; + if ((NSInteger) line.row != lastRowIdx) { + if (lastRowIdx >= 0) { + lineRowsEdge[lastRowIdx] = (ASRowEdge) {.head = lastHead, .foot = lastFoot}; + } + lastRowIdx = line.row; + lineRowsIndex[lastRowIdx] = i; + if (isVerticalForm) { + lastHead = rect.origin.x + rect.size.width; + lastFoot = lastHead - rect.size.width; } else { - font = NULL; + lastHead = rect.origin.y; + lastFoot = lastHead + rect.size.height; } - if (font) { - attrs[(id)kCTFontAttributeName] = (__bridge id)(font); - uiFont = nil; - CFRelease(font); + } else { + if (isVerticalForm) { + lastHead = MAX(lastHead, rect.origin.x + rect.size.width); + lastFoot = MIN(lastFoot, rect.origin.x); + } else { + lastHead = MIN(lastHead, rect.origin.y); + lastFoot = MAX(lastFoot, rect.origin.y + rect.size.height); } - CGColorRef color = (__bridge CGColorRef)(attrs[(id)kCTForegroundColorAttributeName]); - if (color && CFGetTypeID(color) == CGColorGetTypeID() && CGColorGetAlpha(color) == 0) { - // ignore clear color - [attrs removeObjectForKey:(id)kCTForegroundColorAttributeName]; - } - if (!attrs) attrs = [NSMutableDictionary new]; } - truncationToken = [[NSAttributedString alloc] initWithString:ASTextTruncationToken attributes:attrs]; - truncationTokenLine = CTLineCreateWithAttributedString((CFAttributedStringRef)truncationToken); } - if (truncationTokenLine) { - CTLineTruncationType type = kCTLineTruncationEnd; - if (container.truncationType == ASTextTruncationTypeStart) { - type = kCTLineTruncationStart; - } else if (container.truncationType == ASTextTruncationTypeMiddle) { - type = kCTLineTruncationMiddle; + lineRowsEdge[lastRowIdx] = (ASRowEdge) {.head = lastHead, .foot = lastFoot}; + + for (NSUInteger i = 1; i < rowCount; i++) { + ASRowEdge v0 = lineRowsEdge[i - 1]; + ASRowEdge v1 = lineRowsEdge[i]; + lineRowsEdge[i - 1].foot = lineRowsEdge[i].head = (v0.foot + v1.head) * 0.5; + } + } + + { // calculate bounding size + CGRect rect = textBoundingRect; + if (container.path) { + if (container.pathLineWidth > 0) { + CGFloat inset = container.pathLineWidth / 2; + rect = CGRectInset(rect, -inset, -inset); } - NSMutableAttributedString *lastLineText = [text attributedSubstringFromRange:lastLine.range].mutableCopy; - [lastLineText appendAttributedString:truncationToken]; - CTLineRef ctLastLineExtend = CTLineCreateWithAttributedString((CFAttributedStringRef)lastLineText); - if (ctLastLineExtend) { + } else { + rect = UIEdgeInsetsInsetRect(rect, ASTextUIEdgeInsetsInvert(container.insets)); + } + rect = CGRectStandardize(rect); + CGSize size = rect.size; + if (container.verticalForm) { + size.width += container.size.width - (rect.origin.x + rect.size.width); + } else { + size.width += rect.origin.x; + } + size.height += rect.origin.y; + if (size.width < 0) size.width = 0; + if (size.height < 0) size.height = 0; + size.width = ceil(size.width); + size.height = ceil(size.height); + textBoundingSize = size; + } + + visibleRange = ASTextNSRangeFromCFRange(CTFrameGetVisibleStringRange(ctFrame)); + if (needTruncation) { + ASTextLine *lastLine = lines.lastObject; + NSRange lastRange = lastLine.range; + visibleRange.length = lastRange.location + lastRange.length - visibleRange.location; + + // create truncated line + if (container.truncationType != ASTextTruncationTypeNone) { + CTLineRef truncationTokenLine = NULL; + if (container.truncationToken) { + truncationToken = container.truncationToken; + truncationTokenLine = CTLineCreateWithAttributedString((CFAttributedStringRef) truncationToken); + } else { + CFArrayRef runs = CTLineGetGlyphRuns(lastLine.CTLine); + NSUInteger runCount = CFArrayGetCount(runs); + NSMutableDictionary *attrs = nil; + if (runCount > 0) { + CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex(runs, runCount - 1); + attrs = (id) CTRunGetAttributes(run); + attrs = attrs ? attrs.mutableCopy : [NSMutableArray new]; + [attrs removeObjectsForKeys:[NSMutableAttributedString as_allDiscontinuousAttributeKeys]]; + CTFontRef font = (__bridge CTFontRef) attrs[(id) kCTFontAttributeName]; + CGFloat fontSize = font ? CTFontGetSize(font) : 12.0; + UIFont *uiFont = [UIFont systemFontOfSize:fontSize * 0.9]; + if (uiFont) { + font = CTFontCreateWithName((__bridge CFStringRef) uiFont.fontName, uiFont.pointSize, NULL); + } else { + font = NULL; + } + if (font) { + attrs[(id) kCTFontAttributeName] = (__bridge id) (font); + uiFont = nil; + CFRelease(font); + } + CGColorRef color = (__bridge CGColorRef) (attrs[(id) kCTForegroundColorAttributeName]); + if (color && CFGetTypeID(color) == CGColorGetTypeID() && CGColorGetAlpha(color) == 0) { + // ignore clear color + [attrs removeObjectForKey:(id) kCTForegroundColorAttributeName]; + } + if (!attrs) attrs = [NSMutableDictionary new]; + } + truncationToken = [[NSAttributedString alloc] initWithString:ASTextTruncationToken attributes:attrs]; + truncationTokenLine = CTLineCreateWithAttributedString((CFAttributedStringRef) truncationToken); + } + if (truncationTokenLine) { + CTLineTruncationType type = kCTLineTruncationEnd; + if (container.truncationType == ASTextTruncationTypeStart) { + type = kCTLineTruncationStart; + } else if (container.truncationType == ASTextTruncationTypeMiddle) { + type = kCTLineTruncationMiddle; + } + NSMutableAttributedString *lastLineText = [text attributedSubstringFromRange:lastLine.range].mutableCopy; CGFloat truncatedWidth = lastLine.width; + CGFloat atLeastOneLine = lastLine.width; CGRect cgPathRect = CGRectZero; if (CGPathIsRect(cgPath, &cgPathRect)) { if (isVerticalForm) { truncatedWidth = cgPathRect.size.height; - } else { + } else { truncatedWidth = cgPathRect.size.width; } } - CTLineRef ctTruncatedLine = CTLineCreateTruncatedLine(ctLastLineExtend, truncatedWidth, type, truncationTokenLine); - CFRelease(ctLastLineExtend); - if (ctTruncatedLine) { - truncatedLine = [ASTextLine lineWithCTLine:ctTruncatedLine position:lastLine.position vertical:isVerticalForm]; - truncatedLine.index = lastLine.index; - truncatedLine.row = lastLine.row; - CFRelease(ctTruncatedLine); + int i = 0; + if (type != kCTLineTruncationStart) { // Middle or End/Tail wants text preceding truncated content. + i = (int)removedLines.count - 1; + while (atLeastOneLine < truncatedWidth && i >= 0) { + if (lastLineText.length > 0 && [lastLineText.string characterAtIndex:lastLineText.string.length - 1] == '\n') { // Explicit newlines are always "long enough". + [lastLineText deleteCharactersInRange:NSMakeRange(lastLineText.string.length - 1, 1)]; + break; + } + [lastLineText appendAttributedString:[text attributedSubstringFromRange:removedLines[i].range]]; + atLeastOneLine += removedLines[i--].width; + } + [lastLineText appendAttributedString:truncationToken]; } + if (type != kCTLineTruncationEnd && removedLines.count > 0) { // Middle or Start/Head wants text following truncated content. + i = 0; + atLeastOneLine = removedLines[i].width; + while (atLeastOneLine < truncatedWidth && i < removedLines.count) { + atLeastOneLine += removedLines[i++].width; + } + for (i--; i >= 0; i--) { + NSAttributedString *nextLine = [text attributedSubstringFromRange:removedLines[i].range]; + if ([nextLine.string characterAtIndex:nextLine.string.length - 1] == '\n') { // Explicit newlines are always "long enough". + lastLineText = [NSMutableAttributedString new]; + } else { + [lastLineText appendAttributedString:nextLine]; + } + } + [lastLineText insertAttributedString:truncationToken atIndex:0]; + } + + CTLineRef ctLastLineExtend = CTLineCreateWithAttributedString((CFAttributedStringRef) lastLineText); + if (ctLastLineExtend) { + CTLineRef ctTruncatedLine = CTLineCreateTruncatedLine(ctLastLineExtend, truncatedWidth, type, truncationTokenLine); + CFRelease(ctLastLineExtend); + if (ctTruncatedLine) { + truncatedLine = [ASTextLine lineWithCTLine:ctTruncatedLine position:lastLine.position vertical:isVerticalForm]; + truncatedLine.index = lastLine.index; + truncatedLine.row = lastLine.row; + CFRelease(ctTruncatedLine); + } + } + CFRelease(truncationTokenLine); } - CFRelease(truncationTokenLine); } } } @@ -824,7 +883,7 @@ dispatch_semaphore_signal(_lock); if (isVerticalForm) { NSCharacterSet *rotateCharset = ASTextVerticalFormRotateCharacterSet(); NSCharacterSet *rotateMoveCharset = ASTextVerticalFormRotateAndMoveCharacterSet(); - + void (^lineBlock)(ASTextLine *) = ^(ASTextLine *line){ CFArrayRef runs = CTLineGetGlyphRuns(line.CTLine); if (!runs) return; diff --git a/Source/Private/TextExperiment/Component/ASTextLine.m b/Source/Private/TextExperiment/Component/ASTextLine.mm similarity index 99% rename from Source/Private/TextExperiment/Component/ASTextLine.m rename to Source/Private/TextExperiment/Component/ASTextLine.mm index 672b18c7a9..a01311d83c 100644 --- a/Source/Private/TextExperiment/Component/ASTextLine.m +++ b/Source/Private/TextExperiment/Component/ASTextLine.mm @@ -1,5 +1,5 @@ // -// ASTextLine.m +// ASTextLine.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/TextExperiment/String/ASTextAttribute.m b/Source/Private/TextExperiment/String/ASTextAttribute.mm similarity index 99% rename from Source/Private/TextExperiment/String/ASTextAttribute.m rename to Source/Private/TextExperiment/String/ASTextAttribute.mm index fb4b01b6f2..d1abadbe1f 100644 --- a/Source/Private/TextExperiment/String/ASTextAttribute.m +++ b/Source/Private/TextExperiment/String/ASTextAttribute.mm @@ -1,5 +1,5 @@ // -// ASTextAttribute.m +// ASTextAttribute.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/Private/TextExperiment/String/ASTextRunDelegate.m b/Source/Private/TextExperiment/String/ASTextRunDelegate.mm similarity index 98% rename from Source/Private/TextExperiment/String/ASTextRunDelegate.m rename to Source/Private/TextExperiment/String/ASTextRunDelegate.mm index aa4154a91c..1c179b1fea 100644 --- a/Source/Private/TextExperiment/String/ASTextRunDelegate.m +++ b/Source/Private/TextExperiment/String/ASTextRunDelegate.mm @@ -1,5 +1,5 @@ // -// ASTextRunDelegate.m +// ASTextRunDelegate.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Private/TextExperiment/Utility/ASTextUtilities.m b/Source/Private/TextExperiment/Utility/ASTextUtilities.mm similarity index 99% rename from Source/Private/TextExperiment/Utility/ASTextUtilities.m rename to Source/Private/TextExperiment/Utility/ASTextUtilities.mm index 624f73e924..8d0137718b 100644 --- a/Source/Private/TextExperiment/Utility/ASTextUtilities.m +++ b/Source/Private/TextExperiment/Utility/ASTextUtilities.mm @@ -1,5 +1,5 @@ // -// ASTextUtilities.m +// ASTextUtilities.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Private/TextExperiment/Utility/NSAttributedString+ASText.m b/Source/Private/TextExperiment/Utility/NSAttributedString+ASText.mm similarity index 99% rename from Source/Private/TextExperiment/Utility/NSAttributedString+ASText.m rename to Source/Private/TextExperiment/Utility/NSAttributedString+ASText.mm index 134effc161..39f628151c 100644 --- a/Source/Private/TextExperiment/Utility/NSAttributedString+ASText.m +++ b/Source/Private/TextExperiment/Utility/NSAttributedString+ASText.mm @@ -1,5 +1,5 @@ // -// NSAttributedString+ASText.m +// NSAttributedString+ASText.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Private/TextExperiment/Utility/NSParagraphStyle+ASText.m b/Source/Private/TextExperiment/Utility/NSParagraphStyle+ASText.mm similarity index 99% rename from Source/Private/TextExperiment/Utility/NSParagraphStyle+ASText.m rename to Source/Private/TextExperiment/Utility/NSParagraphStyle+ASText.mm index 94680d3f00..bc19fd234c 100644 --- a/Source/Private/TextExperiment/Utility/NSParagraphStyle+ASText.m +++ b/Source/Private/TextExperiment/Utility/NSParagraphStyle+ASText.mm @@ -1,5 +1,5 @@ // -// NSParagraphStyle+ASText.m +// NSParagraphStyle+ASText.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Private/_ASCollectionGalleryLayoutInfo.m b/Source/Private/_ASCollectionGalleryLayoutInfo.mm similarity index 97% rename from Source/Private/_ASCollectionGalleryLayoutInfo.m rename to Source/Private/_ASCollectionGalleryLayoutInfo.mm index 8cca556bac..fec0b52872 100644 --- a/Source/Private/_ASCollectionGalleryLayoutInfo.m +++ b/Source/Private/_ASCollectionGalleryLayoutInfo.mm @@ -1,5 +1,5 @@ // -// _ASCollectionGalleryLayoutInfo.m +// _ASCollectionGalleryLayoutInfo.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Source/Private/_ASHierarchyChangeSet.mm b/Source/Private/_ASHierarchyChangeSet.mm index b852ea2ecd..54ba0bf523 100644 --- a/Source/Private/_ASHierarchyChangeSet.mm +++ b/Source/Private/_ASHierarchyChangeSet.mm @@ -20,11 +20,19 @@ #import #import -// If assertions are enabled, throw. Otherwise log. +// If assertions are enabled and they haven't forced us to suppress the exception, +// then throw, otherwise log. #if ASDISPLAYNODE_ASSERTIONS_ENABLED #define ASFailUpdateValidation(...)\ - NSLog(__VA_ARGS__);\ - [NSException raise:ASCollectionInvalidUpdateException format:__VA_ARGS__]; + _Pragma("clang diagnostic push")\ + _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")\ + if ([ASDisplayNode suppressesInvalidCollectionUpdateExceptions]) {\ + NSLog(__VA_ARGS__);\ + } else {\ + NSLog(__VA_ARGS__);\ + [NSException raise:ASCollectionInvalidUpdateException format:__VA_ARGS__];\ + }\ + _Pragma("clang diagnostic pop") #else #define ASFailUpdateValidation(...) NSLog(__VA_ARGS__); #endif diff --git a/Source/TextKit/ASLayoutManager.m b/Source/TextKit/ASLayoutManager.mm similarity index 98% rename from Source/TextKit/ASLayoutManager.m rename to Source/TextKit/ASLayoutManager.mm index 08370a4bfb..fbb3b49ea4 100644 --- a/Source/TextKit/ASLayoutManager.m +++ b/Source/TextKit/ASLayoutManager.mm @@ -1,5 +1,5 @@ // -// ASLayoutManager.m +// ASLayoutManager.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/TextKit/ASTextKitContext.mm b/Source/TextKit/ASTextKitContext.mm index 0995a66f66..fa0fb88344 100644 --- a/Source/TextKit/ASTextKitContext.mm +++ b/Source/TextKit/ASTextKitContext.mm @@ -32,9 +32,9 @@ { if (self = [super init]) { // Concurrently initialising TextKit components crashes (rdar://18448377) so we use a global lock. - // Allocate __staticMutex on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) - static ASDN::StaticMutex& __staticMutex = *new ASDN::StaticMutex; - ASDN::StaticMutexLocker l(__staticMutex); + // Allocate mutex on the heap to prevent destruction at app exit (https://github.com/TextureGroup/Texture/issues/136) + static auto *mutex = new ASDN::Mutex; + ASDN::MutexLocker l(*mutex); __instanceLock__ = std::make_shared(); @@ -66,7 +66,7 @@ NSTextStorage *, NSTextContainer *))block { - ASDN::MutexSharedLocker l(__instanceLock__); + ASDN::MutexLocker l(*__instanceLock__); if (block) { block(_layoutManager, _textStorage, _textContainer); } diff --git a/Source/TextKit/ASTextKitCoreTextAdditions.m b/Source/TextKit/ASTextKitCoreTextAdditions.mm similarity index 99% rename from Source/TextKit/ASTextKitCoreTextAdditions.m rename to Source/TextKit/ASTextKitCoreTextAdditions.mm index 9b8de67a63..57a1a71e23 100644 --- a/Source/TextKit/ASTextKitCoreTextAdditions.m +++ b/Source/TextKit/ASTextKitCoreTextAdditions.mm @@ -1,5 +1,5 @@ // -// ASTextKitCoreTextAdditions.m +// ASTextKitCoreTextAdditions.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/TextKit/ASTextKitEntityAttribute.m b/Source/TextKit/ASTextKitEntityAttribute.mm similarity index 96% rename from Source/TextKit/ASTextKitEntityAttribute.m rename to Source/TextKit/ASTextKitEntityAttribute.mm index fde0621cf5..4f460dfb7b 100644 --- a/Source/TextKit/ASTextKitEntityAttribute.m +++ b/Source/TextKit/ASTextKitEntityAttribute.mm @@ -1,5 +1,5 @@ // -// ASTextKitEntityAttribute.m +// ASTextKitEntityAttribute.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/TextKit/ASTextKitFontSizeAdjuster.mm b/Source/TextKit/ASTextKitFontSizeAdjuster.mm index 3837771239..1f4a397ac8 100644 --- a/Source/TextKit/ASTextKitFontSizeAdjuster.mm +++ b/Source/TextKit/ASTextKitFontSizeAdjuster.mm @@ -183,8 +183,8 @@ // check to see if we may need to shrink for any of these things BOOL longestWordFits = [longestWordNeedingResize length] ? NO : YES; - BOOL maxLinesFits = _attributes.maximumNumberOfLines > 0 ? NO : YES; - BOOL heightFits = isinf(_constrainedSize.height) ? YES : NO; + BOOL maxLinesFits = self->_attributes.maximumNumberOfLines > 0 ? NO : YES; + BOOL heightFits = isinf(self->_constrainedSize.height) ? YES : NO; CGSize longestWordSize = CGSizeZero; if (longestWordFits == NO) { @@ -204,7 +204,7 @@ if (longestWordFits == NO) { // we need to check the longest word to make sure it fits - longestWordFits = std::ceil((longestWordSize.width * adjustedScale) <= _constrainedSize.width); + longestWordFits = std::ceil((longestWordSize.width * adjustedScale) <= self->_constrainedSize.width); } // if the longest word fits, go ahead and check max line and height. If it didn't fit continue to the next scale factor @@ -216,14 +216,14 @@ // check to see if this scaled string fit in the max lines if (maxLinesFits == NO) { - maxLinesFits = ([self lineCountForString:scaledString] <= _attributes.maximumNumberOfLines); + maxLinesFits = ([self lineCountForString:scaledString] <= self->_attributes.maximumNumberOfLines); } // if max lines still doesn't fit, continue without checking that we fit in the constrained height if (maxLinesFits == YES && heightFits == NO) { // max lines fit so make sure that we fit in the constrained height. CGSize stringSize = [self boundingBoxForString:scaledString]; - heightFits = (stringSize.height <= _constrainedSize.height); + heightFits = (stringSize.height <= self->_constrainedSize.height); } } } diff --git a/Source/TextKit/ASTextKitRenderer.mm b/Source/TextKit/ASTextKitRenderer.mm index a11283bd86..6774dab9ac 100644 --- a/Source/TextKit/ASTextKitRenderer.mm +++ b/Source/TextKit/ASTextKitRenderer.mm @@ -111,11 +111,13 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() _currentScaleFactor = [[self fontSizeAdjuster] scaleFactor]; } + const CGRect constrainedRect = {CGPointZero, _constrainedSize}; + // If we do not scale, do exclusion, or do custom truncation, we should just use NSAttributedString drawing for a fast-path. if (self.canUseFastPath) { CGRect rect = [_attributes.attributedString boundingRectWithSize:_constrainedSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine context:self.stringDrawingContext]; // Intersect with constrained rect, in case text kit goes out-of-bounds. - rect = CGRectIntersection(rect, {CGPointZero, _constrainedSize}); + rect = CGRectIntersection(rect, constrainedRect); _calculatedSize = [self.shadower outsetSizeWithInsetSize:rect.size]; return; } @@ -126,7 +128,7 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() // apply the string scale before truncating or else we may truncate the string after we've done the work to shrink it. [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage]; - [ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:_currentScaleFactor]; + [ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:self->_currentScaleFactor]; scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString]; [textStorage removeLayoutManager:layoutManager]; @@ -136,7 +138,6 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() [[self truncater] truncate]; - CGRect constrainedRect = {CGPointZero, _constrainedSize}; __block CGRect boundingRect; // Force glyph generation and layout, which may not have happened yet (and isn't triggered by @@ -153,7 +154,7 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() // TextKit often returns incorrect glyph bounding rects in the horizontal direction, so we clip to our bounding rect // to make sure our width calculations aren't being offset by glyphs going beyond the constrained rect. - boundingRect = CGRectIntersection(boundingRect, {.size = constrainedRect.size}); + boundingRect = CGRectIntersection(boundingRect, constrainedRect); _calculatedSize = [_shadower outsetSizeWithInsetSize:boundingRect.size]; } @@ -216,7 +217,7 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() if (isScaled) { // if we are going to scale the text, swap out the non-scaled text for the scaled version. NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage]; - [ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:_currentScaleFactor]; + [ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:self->_currentScaleFactor]; scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString]; [textStorage removeLayoutManager:layoutManager]; diff --git a/Source/TextKit/ASTextKitTailTruncater.mm b/Source/TextKit/ASTextKitTailTruncater.mm index 1c4d73f496..3538693460 100644 --- a/Source/TextKit/ASTextKitTailTruncater.mm +++ b/Source/TextKit/ASTextKitTailTruncater.mm @@ -157,7 +157,7 @@ actualGlyphRange:NULL]; // Check if text is truncated, and if so apply our truncation string - if (visibleCharacterRange.length < originalStringLength && _truncationAttributedString.length > 0) { + if (visibleCharacterRange.length < originalStringLength && self->_truncationAttributedString.length > 0) { NSInteger firstCharacterIndexToReplace = [self _calculateCharacterIndexBeforeTruncationMessage:layoutManager textStorage:textStorage textContainer:textContainer]; @@ -171,10 +171,10 @@ textStorage.length - firstCharacterIndexToReplace); // Replace the end of the visible message with the truncation string [textStorage replaceCharactersInRange:truncationReplacementRange - withAttributedString:_truncationAttributedString]; + withAttributedString:self->_truncationAttributedString]; } - _visibleRanges = { visibleCharacterRange }; + self->_visibleRanges = { visibleCharacterRange }; }]; } diff --git a/Source/TextKit/ASTextNodeWordKerner.m b/Source/TextKit/ASTextNodeWordKerner.mm similarity index 99% rename from Source/TextKit/ASTextNodeWordKerner.m rename to Source/TextKit/ASTextNodeWordKerner.mm index fc577d51a4..67e640557c 100644 --- a/Source/TextKit/ASTextNodeWordKerner.m +++ b/Source/TextKit/ASTextNodeWordKerner.mm @@ -1,5 +1,5 @@ // -// ASTextNodeWordKerner.m +// ASTextNodeWordKerner.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/UIImage+ASConvenience.m b/Source/UIImage+ASConvenience.mm similarity index 99% rename from Source/UIImage+ASConvenience.m rename to Source/UIImage+ASConvenience.mm index 557049d311..936514cf14 100644 --- a/Source/UIImage+ASConvenience.m +++ b/Source/UIImage+ASConvenience.mm @@ -1,5 +1,5 @@ // -// UIImage+ASConvenience.m +// UIImage+ASConvenience.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/UIResponder+AsyncDisplayKit.m b/Source/UIResponder+AsyncDisplayKit.mm similarity index 100% rename from Source/UIResponder+AsyncDisplayKit.m rename to Source/UIResponder+AsyncDisplayKit.mm diff --git a/Source/_ASTransitionContext.m b/Source/_ASTransitionContext.mm similarity index 99% rename from Source/_ASTransitionContext.m rename to Source/_ASTransitionContext.mm index a75a3ca434..40a3573c15 100644 --- a/Source/_ASTransitionContext.m +++ b/Source/_ASTransitionContext.mm @@ -1,5 +1,5 @@ // -// _ASTransitionContext.m +// _ASTransitionContext.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/tvOS/ASControlNode+tvOS.m b/Source/tvOS/ASControlNode+tvOS.mm similarity index 99% rename from Source/tvOS/ASControlNode+tvOS.m rename to Source/tvOS/ASControlNode+tvOS.mm index 8a878eb235..a823d9625c 100644 --- a/Source/tvOS/ASControlNode+tvOS.m +++ b/Source/tvOS/ASControlNode+tvOS.mm @@ -1,5 +1,5 @@ // -// ASControlNode+tvOS.m +// ASControlNode+tvOS.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Source/tvOS/ASImageNode+tvOS.m b/Source/tvOS/ASImageNode+tvOS.mm similarity index 98% rename from Source/tvOS/ASImageNode+tvOS.m rename to Source/tvOS/ASImageNode+tvOS.mm index 1bd1ef4599..fa760f1291 100644 --- a/Source/tvOS/ASImageNode+tvOS.m +++ b/Source/tvOS/ASImageNode+tvOS.mm @@ -1,5 +1,5 @@ // -// ASImageNode+tvOS.m +// ASImageNode+tvOS.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -12,6 +12,7 @@ #import #import +// TODO: Remove this – we don't need to link GLKit just to convert degrees to radians. #import #import diff --git a/Tests/ASAbsoluteLayoutSpecSnapshotTests.m b/Tests/ASAbsoluteLayoutSpecSnapshotTests.mm similarity index 98% rename from Tests/ASAbsoluteLayoutSpecSnapshotTests.m rename to Tests/ASAbsoluteLayoutSpecSnapshotTests.mm index 2715872cdc..a1b9b94596 100644 --- a/Tests/ASAbsoluteLayoutSpecSnapshotTests.m +++ b/Tests/ASAbsoluteLayoutSpecSnapshotTests.mm @@ -1,5 +1,5 @@ // -// ASAbsoluteLayoutSpecSnapshotTests.m +// ASAbsoluteLayoutSpecSnapshotTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASBasicImageDownloaderContextTests.m b/Tests/ASBasicImageDownloaderContextTests.mm similarity index 98% rename from Tests/ASBasicImageDownloaderContextTests.m rename to Tests/ASBasicImageDownloaderContextTests.mm index 8414abf007..701174b7dd 100644 --- a/Tests/ASBasicImageDownloaderContextTests.m +++ b/Tests/ASBasicImageDownloaderContextTests.mm @@ -1,5 +1,5 @@ // -// ASBasicImageDownloaderContextTests.m +// ASBasicImageDownloaderContextTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASBasicImageDownloaderTests.m b/Tests/ASBasicImageDownloaderTests.mm similarity index 98% rename from Tests/ASBasicImageDownloaderTests.m rename to Tests/ASBasicImageDownloaderTests.mm index 5eb6da503b..8268dfcd64 100644 --- a/Tests/ASBasicImageDownloaderTests.m +++ b/Tests/ASBasicImageDownloaderTests.mm @@ -1,5 +1,5 @@ // -// ASBasicImageDownloaderTests.m +// ASBasicImageDownloaderTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASBatchFetchingTests.m b/Tests/ASBatchFetchingTests.mm similarity index 99% rename from Tests/ASBatchFetchingTests.m rename to Tests/ASBatchFetchingTests.mm index 76cc6455ba..99b67f05c0 100644 --- a/Tests/ASBatchFetchingTests.m +++ b/Tests/ASBatchFetchingTests.mm @@ -1,5 +1,5 @@ // -// ASBatchFetchingTests.m +// ASBatchFetchingTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASButtonNodeTests.mm b/Tests/ASButtonNodeTests.mm new file mode 100644 index 0000000000..244edd1f0e --- /dev/null +++ b/Tests/ASButtonNodeTests.mm @@ -0,0 +1,54 @@ +// +// ASButtonNodeTests.mm +// Texture +// +// Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import + +#import +#import + +@interface ASButtonNodeTests : XCTestCase +@end + +@implementation ASButtonNodeTests + +- (void)testAccessibility +{ + // Setup a button with some title. + ASButtonNode *buttonNode = nil; + buttonNode = [[ASButtonNode alloc] init]; + NSString *title = @"foo"; + [buttonNode setTitle:title withFont:nil withColor:nil forState:UIControlStateNormal]; + + // Verify accessibility properties. + XCTAssertTrue(buttonNode.accessibilityTraits == UIAccessibilityTraitButton, + @"Should have button accessibility trait, instead has %llu", + buttonNode.accessibilityTraits); + XCTAssertTrue(buttonNode.defaultAccessibilityTraits == UIAccessibilityTraitButton, + @"Default accessibility traits should return button accessibility trait, instead " + @"returns %llu", + buttonNode.defaultAccessibilityTraits); + XCTAssertTrue([buttonNode.accessibilityLabel isEqualToString:title], + @"Accessibility label is incorrectly set to \n%@\n when it should be \n%@\n", + buttonNode.accessibilityLabel, title); + XCTAssertTrue([buttonNode.defaultAccessibilityLabel isEqualToString:title], + @"Default accessibility label incorrectly returns \n%@\n when it should be \n%@\n", + buttonNode.defaultAccessibilityLabel, title); + + // Disable the button and verify that accessibility traits has been updated correctly. + buttonNode.enabled = NO; + UIAccessibilityTraits disabledButtonTrait = UIAccessibilityTraitButton | UIAccessibilityTraitNotEnabled; + XCTAssertTrue(buttonNode.accessibilityTraits == disabledButtonTrait, + @"Should have disabled button accessibility trait, instead has %llu", + buttonNode.accessibilityTraits); + XCTAssertTrue(buttonNode.defaultAccessibilityTraits == disabledButtonTrait, + @"Default accessibility traits should return disabled button accessibility trait, " + @"instead returns %llu", + buttonNode.defaultAccessibilityTraits); +} + +@end diff --git a/Tests/ASCALayerTests.m b/Tests/ASCALayerTests.mm similarity index 99% rename from Tests/ASCALayerTests.m rename to Tests/ASCALayerTests.mm index 3527a272bb..2b30da28fc 100644 --- a/Tests/ASCALayerTests.m +++ b/Tests/ASCALayerTests.mm @@ -1,5 +1,5 @@ // -// ASCALayerTests.m +// ASCALayerTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASCollectionModernDataSourceTests.m b/Tests/ASCollectionModernDataSourceTests.mm similarity index 99% rename from Tests/ASCollectionModernDataSourceTests.m rename to Tests/ASCollectionModernDataSourceTests.mm index d13db9e6cd..5d0a77899a 100644 --- a/Tests/ASCollectionModernDataSourceTests.m +++ b/Tests/ASCollectionModernDataSourceTests.mm @@ -1,5 +1,5 @@ // -// ASCollectionModernDataSourceTests.m +// ASCollectionModernDataSourceTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASCollectionViewFlowLayoutInspectorTests.m b/Tests/ASCollectionViewFlowLayoutInspectorTests.mm similarity index 99% rename from Tests/ASCollectionViewFlowLayoutInspectorTests.m rename to Tests/ASCollectionViewFlowLayoutInspectorTests.mm index c90270df08..555fe21134 100644 --- a/Tests/ASCollectionViewFlowLayoutInspectorTests.m +++ b/Tests/ASCollectionViewFlowLayoutInspectorTests.mm @@ -1,5 +1,5 @@ // -// ASCollectionViewFlowLayoutInspectorTests.m +// ASCollectionViewFlowLayoutInspectorTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASCollectionsTests.m b/Tests/ASCollectionsTests.mm similarity index 98% rename from Tests/ASCollectionsTests.m rename to Tests/ASCollectionsTests.mm index 348798e6d3..ae0313d78c 100644 --- a/Tests/ASCollectionsTests.m +++ b/Tests/ASCollectionsTests.mm @@ -1,5 +1,5 @@ // -// ASCollectionsTests.m +// ASCollectionsTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASConfigurationTests.m b/Tests/ASConfigurationTests.m deleted file mode 100644 index c16cb79e0f..0000000000 --- a/Tests/ASConfigurationTests.m +++ /dev/null @@ -1,71 +0,0 @@ -// -// ASConfigurationTests.m -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import "ASTestCase.h" -#import "ASConfiguration.h" -#import "ASConfigurationDelegate.h" -#import "ASConfigurationInternal.h" - -@interface ASConfigurationTests : ASTestCase - -@end - -@implementation ASConfigurationTests { - void (^onActivate)(ASConfigurationTests *self, ASExperimentalFeatures feature); -} - -- (void)testExperimentalFeatureConfig -{ - // Set the config - ASConfiguration *config = [[ASConfiguration alloc] initWithDictionary:nil]; - config.experimentalFeatures = ASExperimentalGraphicsContexts; - config.delegate = self; - [ASConfigurationManager test_resetWithConfiguration:config]; - - // Set an expectation for a callback, and assert we only get one. - XCTestExpectation *e = [self expectationWithDescription:@"Callbacks done."]; - e.expectedFulfillmentCount = 2; - e.assertForOverFulfill = YES; - onActivate = ^(ASConfigurationTests *self, ASExperimentalFeatures feature) { - [e fulfill]; - }; - - // Now activate the graphics experiment and expect it works. - XCTAssertTrue(ASActivateExperimentalFeature(ASExperimentalGraphicsContexts)); - // We should get a callback here - // Now activate text node and expect it fails. - XCTAssertFalse(ASActivateExperimentalFeature(ASExperimentalTextNode)); - // But we should get another callback. - [self waitForExpectationsWithTimeout:3 handler:nil]; -} - -- (void)textureDidActivateExperimentalFeatures:(ASExperimentalFeatures)feature -{ - if (onActivate) { - onActivate(self, feature); - } -} - -- (void)testMappingNamesToFlags -{ - // Throw in a bad bit. - ASExperimentalFeatures features = ASExperimentalTextNode | ASExperimentalGraphicsContexts | (1 << 22); - NSArray *expectedNames = @[ @"exp_graphics_contexts", @"exp_text_node" ]; - XCTAssertEqualObjects(expectedNames, ASExperimentalFeaturesGetNames(features)); -} - -- (void)testMappingFlagsFromNames -{ - // Throw in a bad name. - NSArray *names = @[ @"exp_text_node", @"exp_graphics_contexts", @"__invalid_name" ]; - ASExperimentalFeatures expected = ASExperimentalGraphicsContexts | ASExperimentalTextNode; - XCTAssertEqual(expected, ASExperimentalFeaturesFromArray(names)); -} - -@end diff --git a/Tests/ASConfigurationTests.mm b/Tests/ASConfigurationTests.mm new file mode 100644 index 0000000000..a563b92049 --- /dev/null +++ b/Tests/ASConfigurationTests.mm @@ -0,0 +1,124 @@ +// +// ASConfigurationTests.m +// Texture +// +// Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import +#import "ASTestCase.h" +#import "ASConfiguration.h" +#import "ASConfigurationDelegate.h" +#import "ASConfigurationInternal.h" + +static ASExperimentalFeatures features[] = { + ASExperimentalGraphicsContexts, + ASExperimentalTextNode, + ASExperimentalInterfaceStateCoalescing, + ASExperimentalUnfairLock, + ASExperimentalLayerDefaults, + ASExperimentalNetworkImageQueue, + ASExperimentalCollectionTeardown, + ASExperimentalFramesetterCache, + ASExperimentalClearDataDuringDeallocation, + ASExperimentalDidEnterPreloadSkipASMLayout +}; + +@interface ASConfigurationTests : ASTestCase + +@end + +@implementation ASConfigurationTests { + void (^onActivate)(ASConfigurationTests *self, ASExperimentalFeatures feature); +} + ++ (NSArray *)names { + return @[ + @"exp_graphics_contexts", + @"exp_text_node", + @"exp_interface_state_coalesce", + @"exp_unfair_lock", + @"exp_infer_layer_defaults", + @"exp_network_image_queue", + @"exp_collection_teardown", + @"exp_framesetter_cache", + @"exp_clear_data_during_deallocation", + @"exp_did_enter_preload_skip_asm_layout", + ]; +} + +- (ASExperimentalFeatures)allFeatures { + ASExperimentalFeatures allFeatures = 0; + for (int i = 0; i < sizeof(features)/sizeof(ASExperimentalFeatures); i++) { + allFeatures |= features[i]; + } + return allFeatures; +} + +- (void)testExperimentalFeatureConfig +{ + // Set the config + ASConfiguration *config = [[ASConfiguration alloc] initWithDictionary:nil]; + config.experimentalFeatures = ASExperimentalGraphicsContexts; + config.delegate = self; + [ASConfigurationManager test_resetWithConfiguration:config]; + + // Set an expectation for a callback, and assert we only get one. + XCTestExpectation *e = [self expectationWithDescription:@"Callbacks done."]; + e.expectedFulfillmentCount = 2; + e.assertForOverFulfill = YES; + onActivate = ^(ASConfigurationTests *self, ASExperimentalFeatures feature) { + [e fulfill]; + }; + + // Now activate the graphics experiment and expect it works. + XCTAssertTrue(ASActivateExperimentalFeature(ASExperimentalGraphicsContexts)); + // We should get a callback here + // Now activate text node and expect it fails. + XCTAssertFalse(ASActivateExperimentalFeature(ASExperimentalTextNode)); + // But we should get another callback. + [self waitForExpectationsWithTimeout:3 handler:nil]; +} + +- (void)textureDidActivateExperimentalFeatures:(ASExperimentalFeatures)feature +{ + if (onActivate) { + onActivate(self, feature); + } +} + +- (void)testMappingNamesToFlags +{ + // Throw in a bad bit. + ASExperimentalFeatures allFeatures = [self allFeatures]; + ASExperimentalFeatures featuresWithBadBit = allFeatures | (1 << 22); + NSArray *expectedNames = [ASConfigurationTests names]; + XCTAssertEqualObjects(expectedNames, ASExperimentalFeaturesGetNames(featuresWithBadBit)); +} + +- (void)testMappingFlagsFromNames +{ + // Throw in a bad name. + NSMutableArray *allNames = [[NSMutableArray alloc] initWithArray:[ASConfigurationTests names]]; + [allNames addObject:@"__invalid_name"]; + ASExperimentalFeatures expected = [self allFeatures]; + XCTAssertEqual(expected, ASExperimentalFeaturesFromArray(allNames)); +} + +- (void)testFlagMatchName +{ + NSArray *names = [ASConfigurationTests names]; + for (NSInteger i = 0; i < names.count; i++) { + XCTAssertEqual(features[i], ASExperimentalFeaturesFromArray(@[names[i]])); + } +} + +- (void)testNameMatchFlag { + NSArray *names = [ASConfigurationTests names]; + for (NSInteger i = 0; i < names.count; i++) { + XCTAssertEqualObjects(@[names[i]], ASExperimentalFeaturesGetNames(features[i])); + } +} + +@end diff --git a/Tests/ASControlNodeTests.m b/Tests/ASControlNodeTests.mm similarity index 99% rename from Tests/ASControlNodeTests.m rename to Tests/ASControlNodeTests.mm index 95207ce9d6..e1c0150a0d 100644 --- a/Tests/ASControlNodeTests.m +++ b/Tests/ASControlNodeTests.mm @@ -1,5 +1,5 @@ // -// ASControlNodeTests.m +// ASControlNodeTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASDispatchTests.m b/Tests/ASDispatchTests.mm similarity index 98% rename from Tests/ASDispatchTests.m rename to Tests/ASDispatchTests.mm index 64c3412f35..a90bce7ed8 100644 --- a/Tests/ASDispatchTests.m +++ b/Tests/ASDispatchTests.mm @@ -1,5 +1,5 @@ // -// ASDispatchTests.m +// ASDispatchTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASDisplayLayerTests.m b/Tests/ASDisplayLayerTests.mm similarity index 96% rename from Tests/ASDisplayLayerTests.m rename to Tests/ASDisplayLayerTests.mm index b65dc3fc4a..2e03eb6da2 100644 --- a/Tests/ASDisplayLayerTests.m +++ b/Tests/ASDisplayLayerTests.mm @@ -1,5 +1,5 @@ // -// ASDisplayLayerTests.m +// ASDisplayLayerTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -285,7 +285,7 @@ static _ASDisplayLayerTestDelegateClassModes _class_modes; - (void)checkDelegateDisplay:(BOOL)displaysAsynchronously { [_ASDisplayLayerTestDelegate setClassModes:_ASDisplayLayerTestDelegateClassModeDisplay]; - _ASDisplayLayerTestDelegate *asyncDelegate = [[_ASDisplayLayerTestDelegate alloc] initWithModes:_ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters]; + _ASDisplayLayerTestDelegate *asyncDelegate = [[_ASDisplayLayerTestDelegate alloc] initWithModes:_ASDisplayLayerTestDelegateMode(_ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters)]; _ASDisplayLayerTestLayer *layer = (_ASDisplayLayerTestLayer *)asyncDelegate.layer; layer.displaysAsynchronously = displaysAsynchronously; @@ -329,7 +329,7 @@ static _ASDisplayLayerTestDelegateClassModes _class_modes; - (void)checkDelegateDrawInContext:(BOOL)displaysAsynchronously { [_ASDisplayLayerTestDelegate setClassModes:_ASDisplayLayerTestDelegateClassModeDrawInContext]; - _ASDisplayLayerTestDelegate *asyncDelegate = [[_ASDisplayLayerTestDelegate alloc] initWithModes:_ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters]; + _ASDisplayLayerTestDelegate *asyncDelegate = [[_ASDisplayLayerTestDelegate alloc] initWithModes:_ASDisplayLayerTestDelegateMode(_ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters)]; _ASDisplayLayerTestLayer *layer = (_ASDisplayLayerTestLayer *)asyncDelegate.layer; layer.displaysAsynchronously = displaysAsynchronously; @@ -375,8 +375,8 @@ static _ASDisplayLayerTestDelegateClassModes _class_modes; - (void)checkDelegateDisplayAndDrawInContext:(BOOL)displaysAsynchronously { - [_ASDisplayLayerTestDelegate setClassModes:_ASDisplayLayerTestDelegateClassModeDisplay | _ASDisplayLayerTestDelegateClassModeDrawInContext]; - _ASDisplayLayerTestDelegate *asyncDelegate = [[_ASDisplayLayerTestDelegate alloc] initWithModes:_ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters]; + [_ASDisplayLayerTestDelegate setClassModes:_ASDisplayLayerTestDelegateClassModes(_ASDisplayLayerTestDelegateClassModeDisplay | _ASDisplayLayerTestDelegateClassModeDrawInContext)]; + _ASDisplayLayerTestDelegate *asyncDelegate = [[_ASDisplayLayerTestDelegate alloc] initWithModes:_ASDisplayLayerTestDelegateMode(_ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters)]; _ASDisplayLayerTestLayer *layer = (_ASDisplayLayerTestLayer *)asyncDelegate.layer; layer.displaysAsynchronously = displaysAsynchronously; @@ -451,7 +451,7 @@ static _ASDisplayLayerTestDelegateClassModes _class_modes; - (void)DISABLED_testTransaction { - _ASDisplayLayerTestDelegateMode delegateModes = _ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters; + auto delegateModes = _ASDisplayLayerTestDelegateMode(_ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters); [_ASDisplayLayerTestDelegate setClassModes:_ASDisplayLayerTestDelegateClassModeDisplay]; // Setup @@ -533,7 +533,7 @@ static _ASDisplayLayerTestDelegateClassModes _class_modes; - (void)checkSuspendResume:(BOOL)displaysAsynchronously { [_ASDisplayLayerTestDelegate setClassModes:_ASDisplayLayerTestDelegateClassModeDrawInContext]; - _ASDisplayLayerTestDelegate *asyncDelegate = [[_ASDisplayLayerTestDelegate alloc] initWithModes:_ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters]; + _ASDisplayLayerTestDelegate *asyncDelegate = [[_ASDisplayLayerTestDelegate alloc] initWithModes:_ASDisplayLayerTestDelegateMode(_ASDisplayLayerTestDelegateModeDidDisplay | _ASDisplayLayerTestDelegateModeDrawParameters)]; _ASDisplayLayerTestLayer *layer = (_ASDisplayLayerTestLayer *)asyncDelegate.layer; layer.displaysAsynchronously = displaysAsynchronously; diff --git a/Tests/ASDisplayNodeAppearanceTests.m b/Tests/ASDisplayNodeAppearanceTests.mm similarity index 95% rename from Tests/ASDisplayNodeAppearanceTests.m rename to Tests/ASDisplayNodeAppearanceTests.mm index 70f9265da7..3b8c1e9df7 100644 --- a/Tests/ASDisplayNodeAppearanceTests.m +++ b/Tests/ASDisplayNodeAppearanceTests.mm @@ -1,5 +1,5 @@ // -// ASDisplayNodeAppearanceTests.m +// ASDisplayNodeAppearanceTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -19,26 +19,26 @@ #import // helper functions -IMP class_replaceMethodWithBlock(Class class, SEL originalSelector, id block); -IMP class_replaceMethodWithBlock(Class class, SEL originalSelector, id block) +IMP class_replaceMethodWithBlock(Class theClass, SEL originalSelector, id block); +IMP class_replaceMethodWithBlock(Class theClass, SEL originalSelector, id block) { IMP newImplementation = imp_implementationWithBlock(block); - Method method = class_getInstanceMethod(class, originalSelector); - return class_replaceMethod(class, originalSelector, newImplementation, method_getTypeEncoding(method)); + Method method = class_getInstanceMethod(theClass, originalSelector); + return class_replaceMethod(theClass, originalSelector, newImplementation, method_getTypeEncoding(method)); } -static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(Class class, SEL originalSelector, void (^block)(id)) +static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(Class theClass, SEL originalSelector, void (^block)(id)) { __block IMP originalImp = NULL; void (^blockActualSwizzle)(id) = ^(id swizzedSelf){ block(swizzedSelf); ((void(*)(id, SEL))originalImp)(swizzedSelf, originalSelector); }; - originalImp = class_replaceMethodWithBlock(class, originalSelector, blockActualSwizzle); + originalImp = class_replaceMethodWithBlock(theClass, originalSelector, blockActualSwizzle); void (^cleanupBlock)(void) = ^{ // restore original method - Method method = class_getInstanceMethod(class, originalSelector); - class_replaceMethod(class, originalSelector, originalImp, method_getTypeEncoding(method)); + Method method = class_getInstanceMethod(theClass, originalSelector); + class_replaceMethod(theClass, originalSelector, originalImp, method_getTypeEncoding(method)); }; return cleanupBlock; }; diff --git a/Tests/ASDisplayNodeExtrasTests.m b/Tests/ASDisplayNodeExtrasTests.mm similarity index 98% rename from Tests/ASDisplayNodeExtrasTests.m rename to Tests/ASDisplayNodeExtrasTests.mm index 8635118388..77d904c2e6 100644 --- a/Tests/ASDisplayNodeExtrasTests.m +++ b/Tests/ASDisplayNodeExtrasTests.mm @@ -1,5 +1,5 @@ // -// ASDisplayNodeExtrasTests.m +// ASDisplayNodeExtrasTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASDisplayNodeImplicitHierarchyTests.m b/Tests/ASDisplayNodeImplicitHierarchyTests.mm similarity index 99% rename from Tests/ASDisplayNodeImplicitHierarchyTests.m rename to Tests/ASDisplayNodeImplicitHierarchyTests.mm index d856002bed..ea41a322b3 100644 --- a/Tests/ASDisplayNodeImplicitHierarchyTests.m +++ b/Tests/ASDisplayNodeImplicitHierarchyTests.mm @@ -1,5 +1,5 @@ // -// ASDisplayNodeImplicitHierarchyTests.m +// ASDisplayNodeImplicitHierarchyTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -11,6 +11,7 @@ #import #import + #import "ASDisplayNodeTestsHelper.h" @interface ASSpecTestDisplayNode : ASDisplayNode diff --git a/Tests/ASDisplayNodeSnapshotTests.m b/Tests/ASDisplayNodeSnapshotTests.mm similarity index 96% rename from Tests/ASDisplayNodeSnapshotTests.m rename to Tests/ASDisplayNodeSnapshotTests.mm index 8d67e3cd08..489727e3ba 100644 --- a/Tests/ASDisplayNodeSnapshotTests.m +++ b/Tests/ASDisplayNodeSnapshotTests.mm @@ -1,5 +1,5 @@ // -// ASDisplayNodeSnapshotTests.m +// ASDisplayNodeSnapshotTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASDisplayNodeTestsHelper.m b/Tests/ASDisplayNodeTestsHelper.mm similarity index 98% rename from Tests/ASDisplayNodeTestsHelper.m rename to Tests/ASDisplayNodeTestsHelper.mm index 3d625414e5..bc145b924d 100644 --- a/Tests/ASDisplayNodeTestsHelper.m +++ b/Tests/ASDisplayNodeTestsHelper.mm @@ -1,5 +1,5 @@ // -// ASDisplayNodeTestsHelper.m +// ASDisplayNodeTestsHelper.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASDisplayViewAccessibilityTests.mm b/Tests/ASDisplayViewAccessibilityTests.mm index e35d1fa0bf..2bdc89e9f4 100644 --- a/Tests/ASDisplayViewAccessibilityTests.mm +++ b/Tests/ASDisplayViewAccessibilityTests.mm @@ -39,4 +39,47 @@ XCTAssertEqual([node.view indexOfAccessibilityElement:node.view.accessibilityElements.firstObject], 0);*/ } +- (void)testThatSubnodeAccessibilityLabelAggregationWorks { + // Setup nodes + ASDisplayNode *node = nil; + ASDisplayNode *innerNode1 = nil; + ASDisplayNode *innerNode2 = nil; + node = [[ASDisplayNode alloc] init]; + innerNode1 = [[ASDisplayNode alloc] init]; + innerNode2 = [[ASDisplayNode alloc] init]; + + // Initialize nodes with relevant accessibility data + node.isAccessibilityContainer = YES; + innerNode1.accessibilityLabel = @"hello"; + innerNode2.accessibilityLabel = @"world"; + + // Attach the subnodes to the parent node, then ensure their accessibility labels have been' + // aggregated to the parent's accessibility label + [node addSubnode:innerNode1]; + [node addSubnode:innerNode2]; + XCTAssertEqualObjects([node.view.accessibilityElements.firstObject accessibilityLabel], + @"hello, world", @"Subnode accessibility label aggregation broken %@", + [node.view.accessibilityElements.firstObject accessibilityLabel]); +} + +- (void)testThatContainerAccessibilityLabelOverrideStopsAggregation { + // Setup nodes + ASDisplayNode *node = nil; + ASDisplayNode *innerNode = nil; + node = [[ASDisplayNode alloc] init]; + innerNode = [[ASDisplayNode alloc] init]; + + // Initialize nodes with relevant accessibility data + node.isAccessibilityContainer = YES; + node.accessibilityLabel = @"hello"; + innerNode.accessibilityLabel = @"world"; + + // Attach the subnode to the parent node, then ensure the parent's accessibility label does not + // get aggregated with the subnode's label + [node addSubnode:innerNode]; + XCTAssertEqualObjects([node.view.accessibilityElements.firstObject accessibilityLabel], @"hello", + @"Container accessibility label override broken %@", + [node.view.accessibilityElements.firstObject accessibilityLabel]); +} + @end diff --git a/Tests/ASEditableTextNodeTests.m b/Tests/ASEditableTextNodeTests.mm similarity index 99% rename from Tests/ASEditableTextNodeTests.m rename to Tests/ASEditableTextNodeTests.mm index a7bbad223a..a359629014 100644 --- a/Tests/ASEditableTextNodeTests.m +++ b/Tests/ASEditableTextNodeTests.mm @@ -1,5 +1,5 @@ // -// ASEditableTextNodeTests.m +// ASEditableTextNodeTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASImageNodeSnapshotTests.m b/Tests/ASImageNodeSnapshotTests.mm similarity index 98% rename from Tests/ASImageNodeSnapshotTests.m rename to Tests/ASImageNodeSnapshotTests.mm index f9c0ca71f9..55cb5f866e 100644 --- a/Tests/ASImageNodeSnapshotTests.m +++ b/Tests/ASImageNodeSnapshotTests.mm @@ -1,5 +1,5 @@ // -// ASImageNodeSnapshotTests.m +// ASImageNodeSnapshotTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASIntegerMapTests.m b/Tests/ASIntegerMapTests.mm similarity index 99% rename from Tests/ASIntegerMapTests.m rename to Tests/ASIntegerMapTests.mm index a79086a614..d23e5bf49f 100644 --- a/Tests/ASIntegerMapTests.m +++ b/Tests/ASIntegerMapTests.mm @@ -1,5 +1,5 @@ // -// ASIntegerMapTests.m +// ASIntegerMapTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASLayoutElementStyleTests.m b/Tests/ASLayoutElementStyleTests.mm similarity index 99% rename from Tests/ASLayoutElementStyleTests.m rename to Tests/ASLayoutElementStyleTests.mm index 4afd67ec4c..f6f95066e8 100644 --- a/Tests/ASLayoutElementStyleTests.m +++ b/Tests/ASLayoutElementStyleTests.mm @@ -1,5 +1,5 @@ // -// ASLayoutElementStyleTests.m +// ASLayoutElementStyleTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASLayoutFlatteningTests.m b/Tests/ASLayoutFlatteningTests.mm similarity index 99% rename from Tests/ASLayoutFlatteningTests.m rename to Tests/ASLayoutFlatteningTests.mm index fb9870c03d..0a1fa02261 100644 --- a/Tests/ASLayoutFlatteningTests.m +++ b/Tests/ASLayoutFlatteningTests.mm @@ -1,5 +1,5 @@ // -// ASLayoutFlatteningTests.m +// ASLayoutFlatteningTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASLayoutSpecSnapshotTestsHelper.m b/Tests/ASLayoutSpecSnapshotTestsHelper.mm similarity index 97% rename from Tests/ASLayoutSpecSnapshotTestsHelper.m rename to Tests/ASLayoutSpecSnapshotTestsHelper.mm index d7385cda95..dec82d4c39 100644 --- a/Tests/ASLayoutSpecSnapshotTestsHelper.m +++ b/Tests/ASLayoutSpecSnapshotTestsHelper.mm @@ -1,5 +1,5 @@ // -// ASLayoutSpecSnapshotTestsHelper.m +// ASLayoutSpecSnapshotTestsHelper.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASLayoutSpecTests.m b/Tests/ASLayoutSpecTests.mm similarity index 99% rename from Tests/ASLayoutSpecTests.m rename to Tests/ASLayoutSpecTests.mm index 257e645499..ff13b66553 100644 --- a/Tests/ASLayoutSpecTests.m +++ b/Tests/ASLayoutSpecTests.mm @@ -1,5 +1,5 @@ // -// ASLayoutSpecTests.m +// ASLayoutSpecTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASMultiplexImageNodeTests.m b/Tests/ASMultiplexImageNodeTests.mm similarity index 99% rename from Tests/ASMultiplexImageNodeTests.m rename to Tests/ASMultiplexImageNodeTests.mm index 56e3b11199..caf86bb48e 100644 --- a/Tests/ASMultiplexImageNodeTests.m +++ b/Tests/ASMultiplexImageNodeTests.mm @@ -1,5 +1,5 @@ // -// ASMultiplexImageNodeTests.m +// ASMultiplexImageNodeTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -100,10 +100,10 @@ // First expect to be hit for the image directly, and fail to return it. OCMExpect([mockDataSource multiplexImageNode:imageNode imageForImageIdentifier:imageIdentifier]) - .andReturn(nil); + .andReturn((id)nil); // BUG: -imageForImageIdentifier is called twice in this case (where we return nil). OCMExpect([mockDataSource multiplexImageNode:imageNode imageForImageIdentifier:imageIdentifier]) - .andReturn(nil); + .andReturn((id)nil); // Then expect to be hit for the URL, which we'll return. OCMExpect([mockDataSource multiplexImageNode:imageNode URLForImageIdentifier:imageIdentifier]) .andReturn([self _testImageURL]); diff --git a/Tests/ASMutableAttributedStringBuilderTests.m b/Tests/ASMutableAttributedStringBuilderTests.mm similarity index 98% rename from Tests/ASMutableAttributedStringBuilderTests.m rename to Tests/ASMutableAttributedStringBuilderTests.mm index 9999b6d4b4..2415dfc626 100644 --- a/Tests/ASMutableAttributedStringBuilderTests.m +++ b/Tests/ASMutableAttributedStringBuilderTests.mm @@ -1,5 +1,5 @@ // -// ASMutableAttributedStringBuilderTests.m +// ASMutableAttributedStringBuilderTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASNavigationControllerTests.m b/Tests/ASNavigationControllerTests.mm similarity index 98% rename from Tests/ASNavigationControllerTests.m rename to Tests/ASNavigationControllerTests.mm index b964029b83..0f42652b01 100644 --- a/Tests/ASNavigationControllerTests.m +++ b/Tests/ASNavigationControllerTests.mm @@ -1,5 +1,5 @@ // -// ASNavigationControllerTests.m +// ASNavigationControllerTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASNetworkImageNodeTests.m b/Tests/ASNetworkImageNodeTests.mm similarity index 99% rename from Tests/ASNetworkImageNodeTests.m rename to Tests/ASNetworkImageNodeTests.mm index 1dcc363e09..6b60030ff9 100644 --- a/Tests/ASNetworkImageNodeTests.m +++ b/Tests/ASNetworkImageNodeTests.mm @@ -1,5 +1,5 @@ // -// ASNetworkImageNodeTests.m +// ASNetworkImageNodeTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. @@ -57,6 +57,7 @@ - (void)testThatProgressBlockIsSetAndClearedCorrectlyOnChangeURL { + [node layer]; [node enterInterfaceState:ASInterfaceStateInHierarchy]; // Set URL while visible, should set progress block diff --git a/Tests/ASPagerNodeTests.m b/Tests/ASPagerNodeTests.mm similarity index 99% rename from Tests/ASPagerNodeTests.m rename to Tests/ASPagerNodeTests.mm index 76ea96c53b..416efaae3d 100644 --- a/Tests/ASPagerNodeTests.m +++ b/Tests/ASPagerNodeTests.mm @@ -1,5 +1,5 @@ // -// ASPagerNodeTests.m +// ASPagerNodeTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASPerformanceTestContext.m b/Tests/ASPerformanceTestContext.mm similarity index 96% rename from Tests/ASPerformanceTestContext.m rename to Tests/ASPerformanceTestContext.mm index 6064a8af9c..15c6787596 100644 --- a/Tests/ASPerformanceTestContext.m +++ b/Tests/ASPerformanceTestContext.mm @@ -1,5 +1,5 @@ // -// ASPerformanceTestContext.m +// ASPerformanceTestContext.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,10 +7,13 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import #import "ASPerformanceTestContext.h" + #import +#import +#import + @interface ASPerformanceTestResult () @property (nonatomic) NSTimeInterval timePer1000; @property (nonatomic) NSString *caseName; @@ -54,6 +57,11 @@ return self; } +- (NSDictionary *)results +{ + return _results; +} + - (void)dealloc { /** diff --git a/Tests/ASPhotosFrameworkImageRequestTests.m b/Tests/ASPhotosFrameworkImageRequestTests.mm similarity index 97% rename from Tests/ASPhotosFrameworkImageRequestTests.m rename to Tests/ASPhotosFrameworkImageRequestTests.mm index dc753bb927..fe1cb408b4 100644 --- a/Tests/ASPhotosFrameworkImageRequestTests.m +++ b/Tests/ASPhotosFrameworkImageRequestTests.mm @@ -1,5 +1,5 @@ // -// ASPhotosFrameworkImageRequestTests.m +// ASPhotosFrameworkImageRequestTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASRecursiveUnfairLockTests.m b/Tests/ASRecursiveUnfairLockTests.mm similarity index 99% rename from Tests/ASRecursiveUnfairLockTests.m rename to Tests/ASRecursiveUnfairLockTests.mm index 38ba7d57d8..3916b319e3 100644 --- a/Tests/ASRecursiveUnfairLockTests.m +++ b/Tests/ASRecursiveUnfairLockTests.mm @@ -1,5 +1,5 @@ // -// ASRecursiveUnfairLockTests.m +// ASRecursiveUnfairLockTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASRunLoopQueueTests.m b/Tests/ASRunLoopQueueTests.mm similarity index 99% rename from Tests/ASRunLoopQueueTests.m rename to Tests/ASRunLoopQueueTests.mm index 89eff024fe..5cb88df8be 100644 --- a/Tests/ASRunLoopQueueTests.m +++ b/Tests/ASRunLoopQueueTests.mm @@ -1,5 +1,5 @@ // -// ASRunLoopQueueTests.m +// ASRunLoopQueueTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASScrollNodeTests.m b/Tests/ASScrollNodeTests.mm similarity index 75% rename from Tests/ASScrollNodeTests.m rename to Tests/ASScrollNodeTests.mm index f0d8fe2079..a58f3f415f 100644 --- a/Tests/ASScrollNodeTests.m +++ b/Tests/ASScrollNodeTests.mm @@ -1,5 +1,5 @@ // -// ASScrollNodeTests.m +// ASScrollNodeTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. @@ -132,4 +132,35 @@ ASXCTAssertEqualSizes(self.scrollNode.view.contentSize, subnodeSize); } +- (void)testASScrollNodeAccessibility { + ASDisplayNode *scrollNode = [[ASDisplayNode alloc] init]; + ASDisplayNode *node = [[ASDisplayNode alloc] init]; + node.isAccessibilityContainer = YES; + node.accessibilityLabel = @"node"; + [scrollNode addSubnode:node]; + node.frame = CGRectMake(0,0,100,100); + ASTextNode2 *text = [[ASTextNode2 alloc] init]; + text.attributedText = [[NSAttributedString alloc] initWithString:@"text"]; + [node addSubnode:text]; + + ASTextNode2 *text2 = [[ASTextNode2 alloc] init]; + text2.attributedText = [[NSAttributedString alloc] initWithString:@"text2"]; + [node addSubnode:text2]; + __unused UIView *view = scrollNode.view; + XCTAssertTrue(node.view.accessibilityElements.firstObject, @"node"); + + // Following tests will only pass when accessibility is enabled. + // More details: https://github.com/TextureGroup/Texture/pull/1188 + + // A bunch of a11y containers each of which hold aggregated labels. + /* NSArray *a11yElements = [scrollNode.view accessibilityElements]; + XCTAssertTrue(a11yElements.count > 0, @"accessibilityElements should exist"); + + UIAccessibilityElement *container = a11yElements.firstObject; + XCTAssertTrue(container.isAccessibilityElement == false && container.accessibilityElements.count > 0); + UIAccessibilityElement *ae = container.accessibilityElements.firstObject; + XCTAssertTrue([[ae accessibilityLabel] isEqualToString:@"node, text, text2"]); + */ +} + @end diff --git a/Tests/ASSnapshotTestCase.m b/Tests/ASSnapshotTestCase.mm similarity index 98% rename from Tests/ASSnapshotTestCase.m rename to Tests/ASSnapshotTestCase.mm index 9fc4e8fd09..560c25988e 100644 --- a/Tests/ASSnapshotTestCase.m +++ b/Tests/ASSnapshotTestCase.mm @@ -1,5 +1,5 @@ // -// ASSnapshotTestCase.m +// ASSnapshotTestCase.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASTabBarControllerTests.m b/Tests/ASTabBarControllerTests.mm similarity index 98% rename from Tests/ASTabBarControllerTests.m rename to Tests/ASTabBarControllerTests.mm index b933222c9f..affde932b6 100644 --- a/Tests/ASTabBarControllerTests.m +++ b/Tests/ASTabBarControllerTests.mm @@ -1,5 +1,5 @@ // -// ASTabBarControllerTests.m +// ASTabBarControllerTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASTableViewThrashTests.m b/Tests/ASTableViewThrashTests.mm similarity index 99% rename from Tests/ASTableViewThrashTests.m rename to Tests/ASTableViewThrashTests.mm index df17ca4ba7..dbf94ba2be 100644 --- a/Tests/ASTableViewThrashTests.m +++ b/Tests/ASTableViewThrashTests.mm @@ -1,5 +1,5 @@ // -// ASTableViewThrashTests.m +// ASTableViewThrashTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASTextKitCoreTextAdditionsTests.m b/Tests/ASTextKitCoreTextAdditionsTests.mm similarity index 98% rename from Tests/ASTextKitCoreTextAdditionsTests.m rename to Tests/ASTextKitCoreTextAdditionsTests.mm index 4a17e0660d..09114a4adb 100644 --- a/Tests/ASTextKitCoreTextAdditionsTests.m +++ b/Tests/ASTextKitCoreTextAdditionsTests.mm @@ -1,5 +1,5 @@ // -// ASTextKitCoreTextAdditionsTests.m +// ASTextKitCoreTextAdditionsTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASTextNode2SnapshotTests.m b/Tests/ASTextNode2SnapshotTests.mm similarity index 99% rename from Tests/ASTextNode2SnapshotTests.m rename to Tests/ASTextNode2SnapshotTests.mm index aba895c323..579ad067c9 100644 --- a/Tests/ASTextNode2SnapshotTests.m +++ b/Tests/ASTextNode2SnapshotTests.mm @@ -1,5 +1,5 @@ // -// ASTextNode2SnapshotTests.m +// ASTextNode2SnapshotTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASTextNode2Tests.mm b/Tests/ASTextNode2Tests.mm new file mode 100644 index 0000000000..2bc513af02 --- /dev/null +++ b/Tests/ASTextNode2Tests.mm @@ -0,0 +1,85 @@ +// +// ASTextNode2Tests.mm +// TextureTests +// +// Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import + +#import "ASTestCase.h" + +#import +#import + +#import + +@interface ASTextNode2Tests : XCTestCase + +@property(nonatomic) ASTextNode2 *textNode; +@property(nonatomic, copy) NSAttributedString *attributedText; + +@end + +@implementation ASTextNode2Tests + +- (void)setUp +{ + [super setUp]; + _textNode = [[ASTextNode2 alloc] init]; + + UIFontDescriptor *desc = [UIFontDescriptor fontDescriptorWithName:@"Didot" size:18]; + NSArray *arr = @[ @{ + UIFontFeatureTypeIdentifierKey : @(kLetterCaseType), + UIFontFeatureSelectorIdentifierKey : @(kSmallCapsSelector) + } ]; + desc = [desc fontDescriptorByAddingAttributes:@{UIFontDescriptorFeatureSettingsAttribute : arr}]; + UIFont *f = [UIFont fontWithDescriptor:desc size:0]; + NSDictionary *d = @{NSFontAttributeName : f}; + NSMutableAttributedString *mas = [[NSMutableAttributedString alloc] + initWithString: + @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor " + @"incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud " + @"exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " + @"dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. " + @"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " + @"mollit anim id est laborum." + attributes:d]; + NSMutableParagraphStyle *para = [NSMutableParagraphStyle new]; + para.alignment = NSTextAlignmentCenter; + para.lineSpacing = 1.0; + [mas addAttribute:NSParagraphStyleAttributeName value:para range:NSMakeRange(0, mas.length - 1)]; + + // Vary the linespacing on the last line + NSMutableParagraphStyle *lastLinePara = [NSMutableParagraphStyle new]; + lastLinePara.alignment = para.alignment; + lastLinePara.lineSpacing = 5.0; + [mas addAttribute:NSParagraphStyleAttributeName + value:lastLinePara + range:NSMakeRange(mas.length - 1, 1)]; + + _attributedText = mas; + _textNode.attributedText = _attributedText; +} + +- (void)testAccessibility +{ + 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.defaultAccessibilityTraits == UIAccessibilityTraitStaticText, + @"Default accessibility traits should return static text accessibility trait, " + @"instead returns %llu", + _textNode.defaultAccessibilityTraits); + + XCTAssertTrue([_textNode.accessibilityLabel isEqualToString:_attributedText.string], + @"Accessibility label is incorrectly set to \n%@\n when it should be \n%@\n", + _textNode.accessibilityLabel, _attributedText.string); + XCTAssertTrue([_textNode.defaultAccessibilityLabel isEqualToString:_attributedText.string], + @"Default accessibility label incorrectly returns \n%@\n when it should be \n%@\n", + _textNode.defaultAccessibilityLabel, _attributedText.string); +} + +@end diff --git a/Tests/ASTextNodePerformanceTests.m b/Tests/ASTextNodePerformanceTests.mm similarity index 99% rename from Tests/ASTextNodePerformanceTests.m rename to Tests/ASTextNodePerformanceTests.mm index ac22bf5bb8..ed055a7b03 100644 --- a/Tests/ASTextNodePerformanceTests.m +++ b/Tests/ASTextNodePerformanceTests.mm @@ -1,5 +1,5 @@ // -// ASTextNodePerformanceTests.m +// ASTextNodePerformanceTests.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/ASTextNodeSnapshotTests.m b/Tests/ASTextNodeSnapshotTests.mm similarity index 99% rename from Tests/ASTextNodeSnapshotTests.m rename to Tests/ASTextNodeSnapshotTests.mm index 068c3896b3..1b21ac35f2 100644 --- a/Tests/ASTextNodeSnapshotTests.m +++ b/Tests/ASTextNodeSnapshotTests.mm @@ -1,5 +1,5 @@ // -// ASTextNodeSnapshotTests.m +// ASTextNodeSnapshotTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASTextNodeTests.m b/Tests/ASTextNodeTests.mm similarity index 84% rename from Tests/ASTextNodeTests.m rename to Tests/ASTextNodeTests.mm index daf8cf7d79..5b23270b50 100644 --- a/Tests/ASTextNodeTests.m +++ b/Tests/ASTextNodeTests.mm @@ -1,5 +1,5 @@ // -// ASTextNodeTests.m +// ASTextNodeTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -50,6 +50,7 @@ @property (nonatomic) ASTextNode *textNode; @property (nonatomic, copy) NSAttributedString *attributedText; +@property (nonatomic) NSMutableArray *textNodeBucket; @end @@ -59,6 +60,7 @@ { [super setUp]; _textNode = [[ASTextNode alloc] init]; + _textNodeBucket = [[NSMutableArray alloc] init]; UIFontDescriptor *desc = [UIFontDescriptor fontDescriptorWithName:@"Didot" size:18]; @@ -247,6 +249,61 @@ XCTAssertEqualObjects(sc2.superclass, [ASTextNodeSubclass class]); } +- (void)testTextNodeSwitchWorksInMultiThreadEnvironment +{ + ASConfiguration *config = [ASConfiguration new]; + config.experimentalFeatures = ASExperimentalTextNode; + [ASConfigurationManager test_resetWithConfiguration:config]; + XCTestExpectation *exp = [self expectationWithDescription:@"wait for full bucket"]; + + dispatch_queue_t queue = dispatch_queue_create("com.texture.AsyncDisplayKit.ASTextNodeTestsQueue", DISPATCH_QUEUE_CONCURRENT); + dispatch_group_t g = dispatch_group_create(); + for (int i = 0; i < 20; i++) { + dispatch_group_async(g, queue, ^{ + ASTextNode *textNode = [[ASTextNodeSecondSubclass alloc] init]; + XCTAssert([textNode isKindOfClass:[ASTextNode2 class]]); + @synchronized(self.textNodeBucket) { + [self.textNodeBucket addObject:textNode]; + if (self.textNodeBucket.count == 20) { + [exp fulfill]; + } + } + }); + } + [self waitForExpectations:@[exp] timeout:3]; + exp = nil; + [self.textNodeBucket removeAllObjects]; +} + +- (void)testTextNodeSwitchWorksInMultiThreadEnvironment2 +{ + ASConfiguration *config = [ASConfiguration new]; + config.experimentalFeatures = ASExperimentalTextNode; + [ASConfigurationManager test_resetWithConfiguration:config]; + XCTestExpectation *exp = [self expectationWithDescription:@"wait for full bucket"]; + + NSLock *lock = [[NSLock alloc] init]; + NSMutableArray *textNodeBucket = [[NSMutableArray alloc] init]; + + dispatch_queue_t queue = dispatch_queue_create("com.texture.AsyncDisplayKit.ASTextNodeTestsQueue", DISPATCH_QUEUE_CONCURRENT); + dispatch_group_t g = dispatch_group_create(); + for (int i = 0; i < 20; i++) { + dispatch_group_async(g, queue, ^{ + ASTextNode *textNode = [[ASTextNodeSecondSubclass alloc] init]; + XCTAssert([textNode isKindOfClass:[ASTextNode2 class]]); + [lock lock]; + [textNodeBucket addObject:textNode]; + if (textNodeBucket.count == 20) { + [exp fulfill]; + } + [lock unlock]; + }); + } + [self waitForExpectations:@[exp] timeout:3]; + exp = nil; + [textNodeBucket removeAllObjects]; +} + @end @implementation ASTextNodeSubclass diff --git a/Tests/ASTraitCollectionTests.m b/Tests/ASTraitCollectionTests.m deleted file mode 100644 index ab201b16d4..0000000000 --- a/Tests/ASTraitCollectionTests.m +++ /dev/null @@ -1,30 +0,0 @@ -// -// ASTraitCollectionTests.m -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -@interface ASTraitCollectionTests : XCTestCase - -@end - -@implementation ASTraitCollectionTests - -- (void)testPrimitiveContentSizeCategoryLifetime -{ - ASPrimitiveContentSizeCategory primitiveContentSize; - @autoreleasepool { - // Make sure the compiler won't optimize string alloc/dealloc - NSString *contentSizeCategory = [NSString stringWithCString:"UICTContentSizeCategoryL" encoding:NSUTF8StringEncoding]; - primitiveContentSize = ASPrimitiveContentSizeCategoryMake(contentSizeCategory); - } - - XCTAssertEqual(primitiveContentSize, UIContentSizeCategoryLarge); -} - -@end diff --git a/Tests/ASUICollectionViewTests.m b/Tests/ASUICollectionViewTests.mm similarity index 83% rename from Tests/ASUICollectionViewTests.m rename to Tests/ASUICollectionViewTests.mm index 8d8a9b9d38..6f99590a84 100644 --- a/Tests/ASUICollectionViewTests.m +++ b/Tests/ASUICollectionViewTests.mm @@ -1,5 +1,5 @@ // -// ASUICollectionViewTests.m +// ASUICollectionViewTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -138,29 +138,4 @@ XCTAssertThrowsSpecificNamed([cv insertSections:[NSIndexSet indexSetWithIndex:0]], NSException, NSInternalInconsistencyException); } -// If you put reloadData in a batch update, collection view will ignore it and perform the normal -// update validation i.e. throw an exception if your data source counts changed. -- (void)testThatPuttingReloadDataInABatchUpdateDoesntWork -{ - UICollectionViewLayout *layout = [[UICollectionViewLayout alloc] init]; - UICollectionView *cv = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) collectionViewLayout:layout]; - id dataSource = [OCMockObject niceMockForProtocol:@protocol(UICollectionViewDataSource)]; - // Start data source at 1 section, 1 item - [[[dataSource stub] andReturnValue:[NSNumber numberWithInteger:1]] numberOfSectionsInCollectionView:cv]; - [[[dataSource expect] andReturnValue:[NSNumber numberWithInteger:1]] collectionView:cv numberOfItemsInSection:0]; - - cv.dataSource = dataSource; - - // Verify initial data. - XCTAssertEqual([cv numberOfSections], 1); - XCTAssertEqual([cv numberOfItemsInSection:0], 1); - [dataSource verify]; - - XCTAssertThrows([cv performBatchUpdates:^{ - // Change data source to 1 section, 2 items - [[[dataSource stub] andReturnValue:[NSNumber numberWithInteger:2]] collectionView:cv numberOfItemsInSection:0]; - [cv reloadData]; - } completion:nil]); -} - @end diff --git a/Tests/ASVideoNodeTests.m b/Tests/ASVideoNodeTests.mm similarity index 98% rename from Tests/ASVideoNodeTests.m rename to Tests/ASVideoNodeTests.mm index 6a4311cfce..81515312d9 100644 --- a/Tests/ASVideoNodeTests.m +++ b/Tests/ASVideoNodeTests.mm @@ -1,5 +1,5 @@ // -// ASVideoNodeTests.m +// ASVideoNodeTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -199,9 +199,9 @@ - (void)doPlayerLayerNodeIsNotAddedIfVisibleButShouldNotBePlaying { [_videoNode pause]; + [_videoNode layer]; [_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay]; - [_videoNode didLoad]; - + XCTAssert(![_videoNode.subnodes containsObject:_videoNode.playerNode]); } @@ -226,7 +226,8 @@ return playerLayer; }]; _videoNode.playerNode.layer.frame = CGRectZero; - + + [_videoNode layer]; [_videoNode didEnterVisibleState]; XCTAssertTrue(_videoNode.shouldBePlaying); @@ -304,7 +305,7 @@ _videoNode.asset = assetMock; _videoNode.shouldAutorepeat = NO; - [_videoNode didLoad]; + [_videoNode layer]; [_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStatePreload]; [_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys]; [_videoNode play]; @@ -325,7 +326,7 @@ _videoNode.asset = assetMock; _videoNode.shouldAutorepeat = YES; - [_videoNode didLoad]; + [_videoNode layer]; [_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStatePreload]; [_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys]; [_videoNode play]; @@ -342,6 +343,7 @@ _videoNode.asset = assetMock; + [_videoNode layer]; [_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStatePreload]; [_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys]; ASCATransactionQueueWait(nil); diff --git a/Tests/ASViewControllerTests.m b/Tests/ASViewControllerTests.mm similarity index 99% rename from Tests/ASViewControllerTests.m rename to Tests/ASViewControllerTests.mm index df050da613..881175d95d 100644 --- a/Tests/ASViewControllerTests.m +++ b/Tests/ASViewControllerTests.mm @@ -1,5 +1,5 @@ // -// ASViewControllerTests.m +// ASViewControllerTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASWeakMapTests.m b/Tests/ASWeakMapTests.mm similarity index 98% rename from Tests/ASWeakMapTests.m rename to Tests/ASWeakMapTests.mm index 4158f0e88c..fd0c0835be 100644 --- a/Tests/ASWeakMapTests.m +++ b/Tests/ASWeakMapTests.mm @@ -1,5 +1,5 @@ // -// ASWeakMapTests.m +// ASWeakMapTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ASWeakSetTests.m b/Tests/ASWeakSetTests.mm similarity index 99% rename from Tests/ASWeakSetTests.m rename to Tests/ASWeakSetTests.mm index 6f64372e3d..31af91de0f 100644 --- a/Tests/ASWeakSetTests.m +++ b/Tests/ASWeakSetTests.mm @@ -1,5 +1,5 @@ // -// ASWeakSetTests.m +// ASWeakSetTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/ArrayDiffingTests.m b/Tests/ArrayDiffingTests.mm similarity index 99% rename from Tests/ArrayDiffingTests.m rename to Tests/ArrayDiffingTests.mm index 45010ffc07..5151449d79 100644 --- a/Tests/ArrayDiffingTests.m +++ b/Tests/ArrayDiffingTests.mm @@ -1,5 +1,5 @@ // -// ArrayDiffingTests.m +// ArrayDiffingTests.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/Common/ASDisplayNode+OCMock.m b/Tests/Common/ASDisplayNode+OCMock.mm similarity index 94% rename from Tests/Common/ASDisplayNode+OCMock.m rename to Tests/Common/ASDisplayNode+OCMock.mm index 051ae9e807..8776fd7bde 100644 --- a/Tests/Common/ASDisplayNode+OCMock.m +++ b/Tests/Common/ASDisplayNode+OCMock.mm @@ -1,5 +1,5 @@ // -// ASDisplayNode+OCMock.m +// ASDisplayNode+OCMock.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/Common/ASTestCase.h b/Tests/Common/ASTestCase.h index 4e8850c247..ed3f5ca55b 100644 --- a/Tests/Common/ASTestCase.h +++ b/Tests/Common/ASTestCase.h @@ -23,10 +23,4 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface ASConfigurationManager (Testing) - -+ (void)test_resetWithConfiguration:(nullable ASConfiguration *)configuration; - -@end - NS_ASSUME_NONNULL_END diff --git a/Tests/Common/ASTestCase.m b/Tests/Common/ASTestCase.mm similarity index 99% rename from Tests/Common/ASTestCase.m rename to Tests/Common/ASTestCase.mm index 7e9d20bf2f..30b42bde4c 100644 --- a/Tests/Common/ASTestCase.m +++ b/Tests/Common/ASTestCase.mm @@ -1,5 +1,5 @@ // -// ASTestCase.m +// ASTestCase.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Tests/Common/NSInvocation+ASTestHelpers.m b/Tests/Common/NSInvocation+ASTestHelpers.mm similarity index 95% rename from Tests/Common/NSInvocation+ASTestHelpers.m rename to Tests/Common/NSInvocation+ASTestHelpers.mm index 5fe505c1f7..dc5a4279f7 100644 --- a/Tests/Common/NSInvocation+ASTestHelpers.m +++ b/Tests/Common/NSInvocation+ASTestHelpers.mm @@ -1,5 +1,5 @@ // -// NSInvocation+ASTestHelpers.m +// NSInvocation+ASTestHelpers.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. diff --git a/Tests/Common/OCMockObject+ASAdditions.m b/Tests/Common/OCMockObject+ASAdditions.mm similarity index 95% rename from Tests/Common/OCMockObject+ASAdditions.m rename to Tests/Common/OCMockObject+ASAdditions.mm index 3ed0930244..e6d3f711d3 100644 --- a/Tests/Common/OCMockObject+ASAdditions.m +++ b/Tests/Common/OCMockObject+ASAdditions.mm @@ -1,5 +1,5 @@ // -// OCMockObject+ASAdditions.m +// OCMockObject+ASAdditions.mm // Texture // // Copyright (c) Pinterest, Inc. All rights reserved. @@ -26,8 +26,8 @@ { // [OCProtocolMockObject respondsToSelector:] <-> [(self) swizzled_protocolMockRespondsToSelector:] Method orig = class_getInstanceMethod(OCMockObject.protocolMockObjectClass, @selector(respondsToSelector:)); - Method new = class_getInstanceMethod(self, @selector(swizzled_protocolMockRespondsToSelector:)); - method_exchangeImplementations(orig, new); + Method newMethod = class_getInstanceMethod(self, @selector(swizzled_protocolMockRespondsToSelector:)); + method_exchangeImplementations(orig, newMethod); // init <-> swizzled_init { @@ -39,8 +39,8 @@ // (class mock) description <-> swizzled_classMockDescription { Method orig = class_getInstanceMethod(OCMockObject.classMockObjectClass, @selector(description)); - Method new = class_getInstanceMethod(self, @selector(swizzled_classMockDescription)); - method_exchangeImplementations(orig, new); + Method newMethod = class_getInstanceMethod(self, @selector(swizzled_classMockDescription)); + method_exchangeImplementations(orig, newMethod); } } diff --git a/Tests/TestHost/AppDelegate.m b/Tests/TestHost/AppDelegate.m deleted file mode 100644 index bf5baf6f9e..0000000000 --- a/Tests/TestHost/AppDelegate.m +++ /dev/null @@ -1,21 +0,0 @@ -// -// AppDelegate.m -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import "AppDelegate.h" -#import -#import - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - return YES; -} - -@end diff --git a/Source/Details/ASCollectionInternal.m b/Tests/TestHost/AppDelegate.mm similarity index 76% rename from Source/Details/ASCollectionInternal.m rename to Tests/TestHost/AppDelegate.mm index 0d50fe3463..91dc913326 100644 --- a/Source/Details/ASCollectionInternal.m +++ b/Tests/TestHost/AppDelegate.mm @@ -1,5 +1,5 @@ // -// ASCollectionInternal.m +// AppDelegate.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,3 +7,8 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import "AppDelegate.h" + +@implementation AppDelegate + +@end diff --git a/Tests/TestHost/main.m b/Tests/TestHost/main.mm similarity index 97% rename from Tests/TestHost/main.m rename to Tests/TestHost/main.mm index 65850400e4..50a9e3ad6a 100644 --- a/Tests/TestHost/main.m +++ b/Tests/TestHost/main.mm @@ -1,5 +1,5 @@ // -// main.m +// main.mm // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. diff --git a/Texture.podspec b/Texture.podspec index c64e8df22c..fa34201dbd 100644 --- a/Texture.podspec +++ b/Texture.podspec @@ -16,7 +16,11 @@ Pod::Spec.new do |spec| # Subspecs spec.subspec 'Core' do |core| - core.compiler_flags = '-fno-exceptions' + + # These will be lowered into subspecs in the future. Only here for ASVideoNode. + core.frameworks = ['AVFoundation', 'CoreMedia'] + + core.compiler_flags = '-fno-exceptions -Wno-implicit-retain-self' core.public_header_files = [ 'Source/*.h', 'Source/Details/**/*.h', @@ -28,8 +32,7 @@ Pod::Spec.new do |spec| ] core.source_files = [ - 'Source/**/*.{h,m,mm}', - 'Base/*.{h,m}', + 'Source/**/*.{h,mm}', # Most TextKit components are not public because the C++ content # in the headers will cause build errors when using @@ -57,7 +60,7 @@ Pod::Spec.new do |spec| end spec.subspec 'MapKit' do |map| - map.frameworks = 'MapKit' + map.frameworks = ['CoreLocation', 'MapKit'] map.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) AS_USE_MAPKIT=1' } map.dependency 'Texture/Core' end diff --git a/docs/Gemfile b/docs/Gemfile index 99e72d8322..dec8af5008 100755 --- a/docs/Gemfile +++ b/docs/Gemfile @@ -2,4 +2,4 @@ source 'https://rubygems.org' gem 'github-pages' gem 'rouge', '~>1.7' -gem 'jekyll', '~>3.2.0' +gem 'jekyll', '~>3.6.3' diff --git a/docs/_docs/image-node.md b/docs/_docs/image-node.md index d7b1057ed7..4fcc2da69b 100755 --- a/docs/_docs/image-node.md +++ b/docs/_docs/image-node.md @@ -6,7 +6,7 @@ prevPage: text-node.html nextPage: network-image-node.html --- -`ASImageNode` is the Texture equivalent to `UIImageView`. The most basic difference is that images are decoded asynchronously by default. Of course, there are more advanced improvments as well such as GIF support and `imageModificationBlock`s. +`ASImageNode` is the Texture equivalent to `UIImageView`. The most basic difference is that images are decoded asynchronously by default. Of course, there are more advanced improvements as well such as GIF support and `imageModificationBlock`s. ### Basic Usage diff --git a/examples/ASDKgram/Sample.xcodeproj/project.pbxproj b/examples/ASDKgram/Sample.xcodeproj/project.pbxproj index 08713d5b1b..97ef0f3c5e 100644 --- a/examples/ASDKgram/Sample.xcodeproj/project.pbxproj +++ b/examples/ASDKgram/Sample.xcodeproj/project.pbxproj @@ -401,6 +401,7 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -443,6 +444,7 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -470,6 +472,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; @@ -489,6 +492,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; diff --git a/examples/ASDKgram/Sample/AppDelegate.m b/examples/ASDKgram/Sample/AppDelegate.m index 019c6a71b2..9058c8f100 100644 --- a/examples/ASDKgram/Sample/AppDelegate.m +++ b/examples/ASDKgram/Sample/AppDelegate.m @@ -39,18 +39,23 @@ // ASDK Home Feed viewController & navController PhotoFeedNodeController *asdkHomeFeedVC = [[PhotoFeedNodeController alloc] init]; UINavigationController *asdkHomeFeedNavCtrl = [[UINavigationController alloc] initWithRootViewController:asdkHomeFeedVC]; + asdkHomeFeedNavCtrl.navigationBar.barStyle = UIBarStyleBlack; asdkHomeFeedNavCtrl.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"ASDK" image:[UIImage imageNamed:@"home"] tag:0]; asdkHomeFeedNavCtrl.hidesBarsOnSwipe = YES; // ListKit Home Feed viewController & navController PhotoFeedListKitViewController *listKitHomeFeedVC = [[PhotoFeedListKitViewController alloc] init]; UINavigationController *listKitHomeFeedNavCtrl = [[UINavigationController alloc] initWithRootViewController:listKitHomeFeedVC]; + listKitHomeFeedNavCtrl.navigationBar.barStyle = UIBarStyleBlack; listKitHomeFeedNavCtrl.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"ListKit" image:[UIImage imageNamed:@"home"] tag:0]; listKitHomeFeedNavCtrl.hidesBarsOnSwipe = YES; + + // UIKit Home Feed viewController & navController PhotoFeedViewController *uikitHomeFeedVC = [[PhotoFeedViewController alloc] init]; UINavigationController *uikitHomeFeedNavCtrl = [[UINavigationController alloc] initWithRootViewController:uikitHomeFeedVC]; + uikitHomeFeedNavCtrl.navigationBar.barStyle = UIBarStyleBlack; uikitHomeFeedNavCtrl.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"UIKit" image:[UIImage imageNamed:@"home"] tag:0]; uikitHomeFeedNavCtrl.hidesBarsOnSwipe = YES; @@ -70,10 +75,6 @@ [[UINavigationBar appearance] setBarTintColor:[UIColor darkBlueColor]]; [[UINavigationBar appearance] setTranslucent:NO]; - // iOS8 hides the status bar in landscape orientation, this forces the status bar hidden status to NO - [application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone]; - [application setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone]; - #if WEAVER WVDebugger *debugger = [WVDebugger defaultInstance]; [debugger enableLayoutElementDebuggingWithApplication:application]; diff --git a/examples/ASDKgram/Sample/Info.plist b/examples/ASDKgram/Sample/Info.plist index 22adc008a5..7641b2f1a3 100644 --- a/examples/ASDKgram/Sample/Info.plist +++ b/examples/ASDKgram/Sample/Info.plist @@ -30,8 +30,6 @@ armv7 - UIStatusBarStyle - UIStatusBarStyleLightContent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait @@ -46,6 +44,6 @@ UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance - + diff --git a/examples/ASDKgram/Sample/PhotoFeedBaseController.m b/examples/ASDKgram/Sample/PhotoFeedBaseController.m index 473f2fc2e3..d94a34e922 100644 --- a/examples/ASDKgram/Sample/PhotoFeedBaseController.m +++ b/examples/ASDKgram/Sample/PhotoFeedBaseController.m @@ -75,6 +75,11 @@ return UIStatusBarStyleLightContent; } +- (BOOL)prefersStatusBarHidden +{ + return NO; +} + - (CGSize)imageSizeForScreenWidth { CGRect screenRect = [[UIScreen mainScreen] bounds]; diff --git a/examples/ASDKgram/Sample/PhotoFeedListKitViewController.m b/examples/ASDKgram/Sample/PhotoFeedListKitViewController.m index 950458e197..997e9451b8 100644 --- a/examples/ASDKgram/Sample/PhotoFeedListKitViewController.m +++ b/examples/ASDKgram/Sample/PhotoFeedListKitViewController.m @@ -28,6 +28,8 @@ UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; ASCollectionNode *node = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout]; if (self = [super initWithNode:node]) { + self.navigationItem.title = @"ListKit"; + CGRect screenRect = [[UIScreen mainScreen] bounds]; CGFloat screenScale = [[UIScreen mainScreen] scale]; CGSize screenWidthImageSize = CGSizeMake(screenRect.size.width * screenScale, screenRect.size.width * screenScale); @@ -81,6 +83,16 @@ return _spinner; } +- (UIStatusBarStyle)preferredStatusBarStyle +{ + return UIStatusBarStyleLightContent; +} + +- (BOOL)prefersStatusBarHidden +{ + return NO; +} + #pragma mark - IGListAdapterDataSource - (NSArray> *)objectsForListAdapter:(IGListAdapter *)listAdapter diff --git a/examples/Kittens/Sample/AppDelegate.m b/examples/Kittens/Sample/AppDelegate.m index d9465e0de7..2395642bd1 100644 --- a/examples/Kittens/Sample/AppDelegate.m +++ b/examples/Kittens/Sample/AppDelegate.m @@ -24,3 +24,14 @@ } @end + +@implementation ASConfiguration (UserProvided) + ++ (ASConfiguration *)textureConfiguration +{ + ASConfiguration *configuration = [ASConfiguration new]; + return configuration; + +} + +@end diff --git a/examples_extra/Placeholders/Sample/PostNode.m b/examples_extra/Placeholders/Sample/PostNode.m index 27809b471d..5c8bbd6dad 100644 --- a/examples_extra/Placeholders/Sample/PostNode.m +++ b/examples_extra/Placeholders/Sample/PostNode.m @@ -72,8 +72,8 @@ - (CGSize)calculateSizeThatFits:(CGSize)constrainedSize { - CGSize textSize = [_textNode measure:constrainedSize]; - CGSize shareSize = [_needyChildNode measure:constrainedSize]; + CGSize textSize = [_textNode layoutThatFits:ASSizeRangeMake(CGSizeZero, constrainedSize)].size; + CGSize shareSize = [_needyChildNode layoutThatFits:ASSizeRangeMake(CGSizeZero, constrainedSize)].size; return CGSizeMake(constrainedSize.width, textSize.height + 10.0 + shareSize.height); } diff --git a/examples_extra/Placeholders/Sample/ViewController.m b/examples_extra/Placeholders/Sample/ViewController.m index f1177963bb..d10f83c55d 100644 --- a/examples_extra/Placeholders/Sample/ViewController.m +++ b/examples_extra/Placeholders/Sample/ViewController.m @@ -61,8 +61,8 @@ CGFloat constrainedWidth = CGRectGetWidth(bounds); CGSize constrainedSize = CGSizeMake(constrainedWidth - 2 * padding, CGFLOAT_MAX); - CGSize postSize = [_postNode measure:constrainedSize]; - CGSize imageSize = [_imageNode measure:constrainedSize]; + CGSize postSize = [_postNode layoutThatFits:ASSizeRangeMake(CGSizeZero, constrainedSize)].size; + CGSize imageSize = [_imageNode layoutThatFits:ASSizeRangeMake(CGSizeZero, constrainedSize)].size; _imageNode.frame = (CGRect){padding, padding, imageSize}; _postNode.frame = (CGRect){padding, CGRectGetMaxY(_imageNode.frame) + 10.0, postSize};