Merge pull request #1485 from garrettmoon/addAnimatedImage

[ASImageNode] Add support for animated GIFs, planning for future animated formats as well.
This commit is contained in:
appleguy 2016-04-15 00:05:43 -07:00
commit 402c5fe25a
30 changed files with 1408 additions and 40 deletions

View File

@ -252,8 +252,26 @@
509E68661B3AEDD7009B9150 /* CGRect+ASConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E201B376416007741D0 /* CGRect+ASConvenience.m */; };
636EA1A41C7FF4EC00EE152F /* NSArray+Diffing.m in Sources */ = {isa = PBXBuildFile; fileRef = DBC452DA1C5BF64600B16017 /* NSArray+Diffing.m */; };
636EA1A51C7FF4EF00EE152F /* ASDefaultPlayButton.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */; };
68355B301CB5799E001D4E68 /* ASImageNode+AnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B2D1CB5799E001D4E68 /* ASImageNode+AnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
68355B311CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */; };
68355B331CB579AD001D4E68 /* ASImageNode+AnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B2D1CB5799E001D4E68 /* ASImageNode+AnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
68355B341CB579B9001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */; };
68355B3A1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */; };
68355B3B1CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */; settings = {ATTRIBUTES = (Public, ); }; };
68355B3C1CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */; };
68355B3D1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */; };
68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */; };
68355B3F1CB57A64001D4E68 /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */; };
68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */; };
68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */; settings = {ATTRIBUTES = (Public, ); }; };
68AF37DB1CBEF4D80077BF76 /* ASImageNode+AnimatedImagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */; };
68B0277A1C1A79CC0041016B /* ASDisplayNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; };
68B0277B1C1A79D60041016B /* ASDisplayNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; };
68B8A4DC1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */; };
68B8A4E11CBDB958007E4543 /* ASWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */; };
68B8A4E21CBDB958007E4543 /* ASWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */; };
68B8A4E31CBDB958007E4543 /* ASWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B8A4E01CBDB958007E4543 /* ASWeakProxy.m */; };
68B8A4E41CBDB958007E4543 /* ASWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B8A4E01CBDB958007E4543 /* ASWeakProxy.m */; };
68EE0DBD1C1B4ED300BA1B99 /* ASMainSerialQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */; };
68EE0DBE1C1B4ED300BA1B99 /* ASMainSerialQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */; };
68EE0DBF1C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */; };
@ -743,7 +761,16 @@
4640521B1A3F83C40061C0BA /* ASFlowLayoutController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASFlowLayoutController.h; sourceTree = "<group>"; };
4640521C1A3F83C40061C0BA /* ASFlowLayoutController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASFlowLayoutController.mm; sourceTree = "<group>"; };
4640521D1A3F83C40061C0BA /* ASLayoutController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutController.h; sourceTree = "<group>"; };
68355B2D1CB5799E001D4E68 /* ASImageNode+AnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASImageNode+AnimatedImage.h"; sourceTree = "<group>"; };
68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASImageNode+AnimatedImage.mm"; sourceTree = "<group>"; };
68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPINRemoteImageDownloader.m; sourceTree = "<group>"; };
68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASImageContainerProtocolCategories.h; sourceTree = "<group>"; };
68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASImageContainerProtocolCategories.m; sourceTree = "<group>"; };
68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPINRemoteImageDownloader.h; sourceTree = "<group>"; };
68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+Beta.h"; sourceTree = "<group>"; };
68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASImageNode+AnimatedImagePrivate.h"; sourceTree = "<group>"; };
68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASWeakProxy.h; sourceTree = "<group>"; };
68B8A4E01CBDB958007E4543 /* ASWeakProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakProxy.m; sourceTree = "<group>"; };
68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMainSerialQueue.h; sourceTree = "<group>"; };
68EE0DBC1C1B4ED300BA1B99 /* ASMainSerialQueue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMainSerialQueue.mm; sourceTree = "<group>"; };
698548611CA9E025008A345F /* ASEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEnvironment.h; sourceTree = "<group>"; };
@ -1023,6 +1050,8 @@
0587F9BC1A7309ED00AFF0BA /* ASEditableTextNode.mm */,
058D09DD195D050800B7D73C /* ASImageNode.h */,
058D09DE195D050800B7D73C /* ASImageNode.mm */,
68355B2D1CB5799E001D4E68 /* ASImageNode+AnimatedImage.h */,
68355B2E1CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm */,
0516FA3E1A1563D200B4EBED /* ASMultiplexImageNode.h */,
0516FA3F1A1563D200B4EBED /* ASMultiplexImageNode.mm */,
055B9FA61A1C154B00035D6D /* ASNetworkImageNode.h */,
@ -1150,9 +1179,13 @@
4640521C1A3F83C40061C0BA /* ASFlowLayoutController.mm */,
058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */,
058D09E7195D050800B7D73C /* ASHighlightOverlayLayer.mm */,
05F20AA31A15733C00DCA68A /* ASImageProtocols.h */,
430E7C8D1B4C23F100697A4C /* ASIndexPath.h */,
430E7C8E1B4C23F100697A4C /* ASIndexPath.m */,
05F20AA31A15733C00DCA68A /* ASImageProtocols.h */,
68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */,
68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */,
68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */,
68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */,
4640521D1A3F83C40061C0BA /* ASLayoutController.h */,
292C59991A956527007E5DD6 /* ASLayoutRangeType.h */,
68EE0DBB1C1B4ED300BA1B99 /* ASMainSerialQueue.h */,
@ -1169,6 +1202,8 @@
296A0A311A951715005ACEAA /* ASScrollDirection.h */,
205F0E111B371BD7007741D0 /* ASScrollDirection.m */,
058D0A12195D050800B7D73C /* ASThread.h */,
68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */,
68B8A4E01CBDB958007E4543 /* ASWeakProxy.m */,
205F0E1F1B376416007741D0 /* CGRect+ASConvenience.h */,
205F0E201B376416007741D0 /* CGRect+ASConvenience.m */,
25B171EA1C12242700508A7A /* Data Controller */,
@ -1226,6 +1261,7 @@
69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */,
058D0A0D195D050800B7D73C /* ASImageNode+CGExtras.h */,
058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.m */,
68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */,
ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */,
ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.mm */,
ACF6ED451B17847A00DA7C62 /* ASLayoutSpecUtilities.h */,
@ -1407,6 +1443,7 @@
058D0A6D195D05EC00B7D73C /* _ASAsyncTransactionGroup.h in Headers */,
058D0A72195D05F800B7D73C /* _ASCoreAnimationExtras.h in Headers */,
7A06A73B1C35F08800FE8DAA /* ASRelativeLayoutSpec.h in Headers */,
68B8A4DC1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h in Headers */,
058D0A53195D05DC00B7D73C /* _ASDisplayLayer.h in Headers */,
058D0A55195D05DC00B7D73C /* _ASDisplayView.h in Headers */,
B13CA0F71C519E9400E031AB /* ASCollectionViewLayoutFacilitatorProtocol.h in Headers */,
@ -1444,12 +1481,14 @@
ACF6ED201B17843500DA7C62 /* ASDimension.h in Headers */,
058D0A78195D05F900B7D73C /* ASDisplayNode+DebugTiming.h in Headers */,
DECBD6E71BE56E1900CF4905 /* ASButtonNode.h in Headers */,
68B8A4E11CBDB958007E4543 /* ASWeakProxy.h in Headers */,
DBC452DB1C5BF64600B16017 /* NSArray+Diffing.h in Headers */,
058D0A4C195D05CB00B7D73C /* ASDisplayNode+Subclasses.h in Headers */,
058D0A4A195D05CB00B7D73C /* ASDisplayNode.h in Headers */,
058D0A84195D060300B7D73C /* ASDisplayNodeExtraIvars.h in Headers */,
AC7A2C171BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */,
058D0A4D195D05CB00B7D73C /* ASDisplayNodeExtras.h in Headers */,
68355B3B1CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h in Headers */,
68B0277A1C1A79CC0041016B /* ASDisplayNode+Beta.h in Headers */,
767E7F8D1C9019130066C000 /* AsyncDisplayKit+Debug.h in Headers */,
257754B11BEE44CD00737CA5 /* ASTextKitShadower.h in Headers */,
@ -1470,6 +1509,7 @@
ACF6ED221B17843500DA7C62 /* ASInsetLayoutSpec.h in Headers */,
ACF6ED4B1B17847A00DA7C62 /* ASInternalHelpers.h in Headers */,
DB55C2661C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */,
68355B3D1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h in Headers */,
ACF6ED241B17843500DA7C62 /* ASLayout.h in Headers */,
251B8EFB1BBB3D690087C538 /* ASDataController+Subclasses.h in Headers */,
ACF6ED2A1B17843500DA7C62 /* ASLayoutable.h in Headers */,
@ -1500,6 +1540,7 @@
257754C31BEE458E00737CA5 /* ASTextNodeTypes.h in Headers */,
9C49C36F1B853957000B0DD5 /* ASStackLayoutable.h in Headers */,
69E1006D1CA89CB600D88C1B /* ASEnvironmentInternal.h in Headers */,
68355B301CB5799E001D4E68 /* ASImageNode+AnimatedImage.h in Headers */,
AC21EC101B3D0BF600C8B19A /* ASStackLayoutDefines.h in Headers */,
CC7FD9DE1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */,
ACF6ED2F1B17843500DA7C62 /* ASStackLayoutSpec.h in Headers */,
@ -1542,6 +1583,7 @@
B35062481B010EFD0018CF92 /* _AS-objc-internal.h in Headers */,
69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */,
B350623C1B010EFD0018CF92 /* _ASAsyncTransaction.h in Headers */,
68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */,
7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */,
B350623F1B010EFD0018CF92 /* _ASAsyncTransactionContainer.h in Headers */,
B13CA1011C52004900E031AB /* ASCollectionNode+Beta.h in Headers */,
@ -1563,8 +1605,10 @@
254C6B731BF94DF4003EC431 /* ASTextKitCoreTextAdditions.h in Headers */,
254C6B7A1BF94DF4003EC431 /* ASTextKitRenderer.h in Headers */,
69CB62AC1CB8165900024920 /* _ASDisplayViewAccessiblity.h in Headers */,
68355B3F1CB57A64001D4E68 /* ASPINRemoteImageDownloader.h in Headers */,
254C6B7C1BF94DF4003EC431 /* ASTextKitRenderer+TextChecking.h in Headers */,
34EFC7611B701C9C00AD841F /* ASBackgroundLayoutSpec.h in Headers */,
68AF37DB1CBEF4D80077BF76 /* ASImageNode+AnimatedImagePrivate.h in Headers */,
B35062591B010F070018CF92 /* ASBaseDefines.h in Headers */,
B35062131B010EFD0018CF92 /* ASBasicImageDownloader.h in Headers */,
B35062461B010EFD0018CF92 /* ASBasicImageDownloaderInternal.h in Headers */,
@ -1610,10 +1654,12 @@
34EFC75F1B701C8600AD841F /* ASInsetLayoutSpec.h in Headers */,
34EFC75D1B701BE900AD841F /* ASInternalHelpers.h in Headers */,
34EFC7671B701CD900AD841F /* ASLayout.h in Headers */,
68355B331CB579AD001D4E68 /* ASImageNode+AnimatedImage.h in Headers */,
DEC146B71C37A16A004A0EE7 /* ASCollectionInternal.h in Headers */,
DBDB83951C6E879900D0098C /* ASPagerFlowLayout.h in Headers */,
34EFC7691B701CE100AD841F /* ASLayoutable.h in Headers */,
9CDC18CD1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */,
68B8A4E21CBDB958007E4543 /* ASWeakProxy.h in Headers */,
B35062201B010EFD0018CF92 /* ASLayoutController.h in Headers */,
B35062211B010EFD0018CF92 /* ASLayoutRangeType.h in Headers */,
34EFC76A1B701CE600AD841F /* ASLayoutSpec.h in Headers */,
@ -1886,13 +1932,16 @@
E55D86321CA8A14000A0C26F /* ASLayoutable.mm in Sources */,
058D0A23195D050800B7D73C /* _ASAsyncTransactionContainer.m in Sources */,
058D0A24195D050800B7D73C /* _ASAsyncTransactionGroup.m in Sources */,
68355B3A1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m in Sources */,
DBDB83961C6E879900D0098C /* ASPagerFlowLayout.m in Sources */,
058D0A26195D050800B7D73C /* _ASCoreAnimationExtras.mm in Sources */,
257754B41BEE44CD00737CA5 /* ASTextKitTailTruncater.mm in Sources */,
68B8A4E31CBDB958007E4543 /* ASWeakProxy.m in Sources */,
69E1006F1CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */,
AC026B711BD57DBF00BBC17E /* _ASHierarchyChangeSet.m in Sources */,
257754BF1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.m in Sources */,
058D0A18195D050800B7D73C /* _ASDisplayLayer.mm in Sources */,
68355B3C1CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m in Sources */,
68EE0DBF1C1B4ED300BA1B99 /* ASMainSerialQueue.mm in Sources */,
058D0A19195D050800B7D73C /* _ASDisplayView.mm in Sources */,
9C55866A1BD549CB00B50E3A /* ASAsciiArtBoxCreator.m in Sources */,
@ -1973,6 +2022,7 @@
81EE38501C8E94F000456208 /* ASRunLoopQueue.mm in Sources */,
ACF6ED321B17843500DA7C62 /* ASStaticLayoutSpec.mm in Sources */,
AC026B6B1BD57D6F00BBC17E /* ASChangeSetDataController.m in Sources */,
68355B311CB5799E001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */,
055F1A3519ABD3E3004DAFF1 /* ASTableView.mm in Sources */,
058D0A17195D050800B7D73C /* ASTextNode.mm in Sources */,
257754AC1BEE44CD00737CA5 /* ASTextKitRenderer.mm in Sources */,
@ -2062,6 +2112,7 @@
34EFC7641B701CC600AD841F /* ASCenterLayoutSpec.mm in Sources */,
18C2ED831B9B7DE800F627B3 /* ASCollectionNode.mm in Sources */,
E55D86331CA8A14000A0C26F /* ASLayoutable.mm in Sources */,
68B8A4E41CBDB958007E4543 /* ASWeakProxy.m in Sources */,
69CB62AE1CB8165900024920 /* _ASDisplayViewAccessiblity.mm in Sources */,
B35061F61B010EFD0018CF92 /* ASCollectionView.mm in Sources */,
509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.mm in Sources */,
@ -2077,6 +2128,7 @@
DEC146B91C37A16A004A0EE7 /* ASCollectionInternal.m in Sources */,
69E100701CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */,
254C6B891BF94F8A003EC431 /* ASTextKitRenderer+Positioning.mm in Sources */,
68355B341CB579B9001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */,
E5711A301C840C96009619D4 /* ASIndexedNodeContext.m in Sources */,
B35062511B010EFD0018CF92 /* ASDisplayNode+UIViewBridge.mm in Sources */,
B35061FC1B010EFD0018CF92 /* ASDisplayNode.mm in Sources */,
@ -2087,6 +2139,7 @@
B350621C1B010EFD0018CF92 /* ASFlowLayoutController.mm in Sources */,
B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */,
B35062541B010EFD0018CF92 /* ASImageNode+CGExtras.m in Sources */,
68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.m in Sources */,
B35062031B010EFD0018CF92 /* ASImageNode.mm in Sources */,
254C6B821BF94F8A003EC431 /* ASTextKitComponents.m in Sources */,
430E7C921B4C23F100697A4C /* ASIndexPath.m in Sources */,
@ -2123,6 +2176,7 @@
DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.m in Sources */,
B350620B1B010EFD0018CF92 /* ASTableView.mm in Sources */,
B350620E1B010EFD0018CF92 /* ASTextNode.mm in Sources */,
68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */,
C78F7E2A1BF7808300CDEAFC /* ASTableNode.m in Sources */,
509E68661B3AEDD7009B9150 /* CGRect+ASConvenience.m in Sources */,
254C6B8D1BF94F8A003EC431 /* ASEqualityHashHelpers.mm in Sources */,

View File

@ -0,0 +1,15 @@
//
// ASImageNode+AnimatedImage.h
// AsyncDisplayKit
//
// Created by Garrett Moon on 3/22/16.
// Copyright © 2016 Facebook. All rights reserved.
//
#import "ASImageNode.h"
#import "ASImageProtocols.h"
@interface ASImageNode ()
@property (atomic, assign) BOOL animatedImagePaused;
@property (nullable, atomic, strong) id <ASAnimatedImageProtocol> animatedImage;
@end

View File

@ -0,0 +1,226 @@
//
// ASImageNode+AnimatedImage.m
// AsyncDisplayKit
//
// Created by Garrett Moon on 3/22/16.
// Copyright © 2016 Facebook. All rights reserved.
//
#import "ASImageNode+AnimatedImage.h"
#import "ASAssert.h"
#import "ASImageProtocols.h"
#import "ASDisplayNode+Subclasses.h"
#import "ASDisplayNodeExtras.h"
#import "ASEqualityHelpers.h"
#import "ASDisplayNode+FrameworkPrivate.h"
#import "ASImageNode+AnimatedImagePrivate.h"
#import "ASInternalHelpers.h"
#import "ASWeakProxy.h"
@implementation ASImageNode (AnimatedImage)
#pragma mark - GIF support
- (void)setAnimatedImage:(id <ASAnimatedImageProtocol>)animatedImage
{
ASDN::MutexLocker l(_animatedImageLock);
if (!ASObjectIsEqual(_animatedImage, animatedImage)) {
_animatedImage = animatedImage;
}
if (animatedImage != nil) {
__weak ASImageNode *weakSelf = self;
if ([animatedImage respondsToSelector:@selector(setCoverImageReadyCallback:)]) {
animatedImage.coverImageReadyCallback = ^(UIImage *coverImage) {
[weakSelf coverImageCompleted:coverImage];
};
}
animatedImage.playbackReadyCallback = ^{
[weakSelf animatedImageFileReady];
};
}
}
- (id <ASAnimatedImageProtocol>)animatedImage
{
ASDN::MutexLocker l(_animatedImageLock);
return _animatedImage;
}
- (void)setAnimatedImagePaused:(BOOL)animatedImagePaused
{
ASDN::MutexLocker l(_animatedImagePausedLock);
_animatedImagePaused = animatedImagePaused;
ASPerformBlockOnMainThread(^{
if (animatedImagePaused) {
[self stopAnimating];
} else {
[self startAnimating];
}
});
}
- (BOOL)animatedImagePaused
{
ASDN::MutexLocker l(_animatedImagePausedLock);
return _animatedImagePaused;
}
- (void)coverImageCompleted:(UIImage *)coverImage
{
BOOL setCoverImage = YES;
{
ASDN::MutexLocker l(_displayLinkLock);
if (_displayLink != nil && _displayLink.paused == NO) {
setCoverImage = NO;
}
}
if (setCoverImage) {
self.image = coverImage;
}
}
- (void)animatedImageFileReady
{
dispatch_async(dispatch_get_main_queue(), ^{
[self startAnimating];
});
}
- (void)startAnimating
{
ASDisplayNodeAssertMainThread();
if (ASInterfaceStateIncludesVisible(self.interfaceState) == NO) {
return;
}
if (self.animatedImagePaused) {
return;
}
if (self.animatedImage.playbackReady == NO) {
return;
}
#if ASAnimatedImageDebug
NSLog(@"starting animation: %p", self);
#endif
ASDN::MutexLocker l(_displayLinkLock);
if (_displayLink == nil) {
_playHead = 0;
_displayLink = [CADisplayLink displayLinkWithTarget:[ASWeakProxy weakProxyWithTarget:self] selector:@selector(displayLinkFired:)];
_displayLink.frameInterval = self.animatedImage.frameInterval;
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
} else {
_displayLink.paused = NO;
}
}
- (void)stopAnimating
{
#if ASAnimatedImageDebug
NSLog(@"stopping animation: %p", self);
#endif
ASDisplayNodeAssertMainThread();
ASDN::MutexLocker l(_displayLinkLock);
_displayLink.paused = YES;
self.lastDisplayLinkFire = 0;
[self.animatedImage clearAnimatedImageCache];
}
- (void)visibilityDidChange:(BOOL)isVisible
{
[super visibilityDidChange:isVisible];
ASDisplayNodeAssertMainThread();
if (isVisible) {
if (self.animatedImage.coverImageReady) {
self.image = self.animatedImage.coverImage;
}
[self startAnimating];
} else {
[self stopAnimating];
}
}
- (void)__enterHierarchy
{
[super __enterHierarchy];
[self startAnimating];
}
- (void)__exitHierarchy
{
[super __exitHierarchy];
[self stopAnimating];
}
- (void)displayLinkFired:(CADisplayLink *)displayLink
{
ASDisplayNodeAssertMainThread();
CFTimeInterval timeBetweenLastFire;
if (self.lastDisplayLinkFire == 0) {
timeBetweenLastFire = 0;
} else {
timeBetweenLastFire = CACurrentMediaTime() - self.lastDisplayLinkFire;
}
self.lastDisplayLinkFire = CACurrentMediaTime();
_playHead += timeBetweenLastFire;
while (_playHead > self.animatedImage.totalDuration) {
_playHead -= self.animatedImage.totalDuration;
_playedLoops++;
}
if (self.animatedImage.loopCount > 0 && _playedLoops >= self.animatedImage.loopCount) {
[self stopAnimating];
return;
}
NSUInteger frameIndex = [self frameIndexAtPlayHeadPosition:_playHead];
CGImageRef frameImage = [self.animatedImage imageAtIndex:frameIndex];
if (frameImage == nil) {
_playHead -= timeBetweenLastFire;
//Pause the display link until we get a file ready notification
displayLink.paused = YES;
self.lastDisplayLinkFire = 0;
} else {
self.contents = (__bridge id)frameImage;
}
}
- (NSUInteger)frameIndexAtPlayHeadPosition:(CFTimeInterval)playHead
{
ASDisplayNodeAssertMainThread();
NSUInteger frameIndex = 0;
for (NSUInteger durationIndex = 0; durationIndex < self.animatedImage.frameCount; durationIndex++) {
playHead -= [self.animatedImage durationAtIndex:durationIndex];
if (playHead < 0) {
return frameIndex;
}
frameIndex++;
}
return frameIndex;
}
- (void)dealloc
{
ASDN::MutexLocker l(_displayLinkLock);
#if ASAnimatedImageDebug
if (_displayLink) {
NSLog(@"invalidating display link");
}
#endif
[_displayLink invalidate];
_displayLink = nil;
}
@end

View File

@ -16,6 +16,8 @@
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
#import <AsyncDisplayKit/ASTextNode.h>
#import <AsyncDisplayKit/ASImageNode+AnimatedImage.h>
#import <AsyncDisplayKit/ASImageNode+AnimatedImagePrivate.h>
#import "ASImageNode+CGExtras.h"
#import "AsyncDisplayKit+Debug.h"

View File

@ -738,8 +738,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
if (_cache) {
if (_cacheSupportsNewProtocol) {
[_cache cachedImageWithURL:imageURL callbackQueue:dispatch_get_main_queue() completion:^(UIImage *imageFromCache) {
completionBlock(imageFromCache);
[_cache cachedImageWithURL:imageURL callbackQueue:dispatch_get_main_queue() completion:^(id <ASImageContainerProtocol> imageContainer) {
completionBlock([imageContainer asdk_image]);
}];
} else {
#pragma clang diagnostic push
@ -784,7 +784,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
[self _setDownloadIdentifier:[_downloader downloadImageWithURL:imageURL
callbackQueue:dispatch_get_main_queue()
downloadProgress:downloadProgressBlock
completion:^(UIImage *downloadedImage, NSError *error, id downloadIdentifier) {
completion:^(id <ASImageContainerProtocol> imageContainer, NSError *error, id downloadIdentifier) {
// We dereference iVars directly, so we can't have weakSelf going nil on us.
__typeof__(self) strongSelf = weakSelf;
if (!strongSelf)
@ -796,7 +796,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
return;
}
completionBlock(downloadedImage, error);
completionBlock([imageContainer asdk_image], error);
// Delegateify.
if (strongSelf->_delegateFlags.downloadFinish)

View File

@ -14,6 +14,8 @@
#import "ASEqualityHelpers.h"
#import "ASThread.h"
#import "ASInternalHelpers.h"
#import "ASImageContainerProtocolCategories.h"
#import "ASImageNode+AnimatedImage.h"
#if PIN_REMOTE_IMAGE
#import "ASPINRemoteImageDownloader.h"
@ -46,6 +48,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
BOOL _downloaderSupportsNewProtocol;
BOOL _downloaderImplementsSetProgress;
BOOL _downloaderImplementsSetPriority;
BOOL _downloaderImplementsAnimatedImage;
BOOL _cacheSupportsNewProtocol;
BOOL _cacheSupportsClearing;
@ -71,6 +74,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
_downloaderImplementsSetProgress = [downloader respondsToSelector:@selector(setProgressImageBlock:callbackQueue:withDownloadIdentifier:)];
_downloaderImplementsSetPriority = [downloader respondsToSelector:@selector(setPriority:withDownloadIdentifier:)];
_downloaderImplementsAnimatedImage = [downloader respondsToSelector:@selector(animatedImageWithData:)];
_cacheSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)];
_cacheSupportsClearing = [cache respondsToSelector:@selector(clearFetchedImageFromCacheWithURL:)];
@ -188,7 +192,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
if (_cacheSupportsSynchronousFetch) {
ASDN::MutexLocker l(_lock);
if (_imageLoaded == NO && _URL && _downloadIdentifier == nil) {
UIImage *result = [_cache synchronouslyFetchedCachedImageWithURL:_URL];
UIImage *result = [[_cache synchronouslyFetchedCachedImageWithURL:_URL] asdk_image];
if (result) {
self.image = result;
_imageLoaded = YES;
@ -291,6 +295,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
image = nil;
});
}
self.animatedImage = nil;
self.image = _defaultImage;
_imageLoaded = NO;
}
@ -309,7 +314,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
_cacheUUID = nil;
}
- (void)_downloadImageWithCompletion:(void (^)(UIImage *image, NSError*, id downloadIdentifier))finished
- (void)_downloadImageWithCompletion:(void (^)(id <ASImageContainerProtocol> imageContainer, NSError*, id downloadIdentifier))finished
{
ASPerformBlockOnBackgroundThread(^{
ASDN::MutexLocker l(_lock);
@ -317,9 +322,9 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
_downloadIdentifier = [_downloader downloadImageWithURL:_URL
callbackQueue:dispatch_get_main_queue()
downloadProgress:NULL
completion:^(UIImage * _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier) {
completion:^(id <ASImageContainerProtocol> _Nullable imageContainer, NSError * _Nullable error, id _Nullable downloadIdentifier) {
if (finished != NULL) {
finished(image, error, downloadIdentifier);
finished(imageContainer, error, downloadIdentifier);
}
}];
} else {
@ -376,7 +381,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
}
} else {
__weak __typeof__(self) weakSelf = self;
void (^finished)(UIImage *, NSError *, id downloadIdentifier) = ^(UIImage *responseImage, NSError *error, id downloadIdentifier) {
void (^finished)(id <ASImageContainerProtocol>, NSError *, id downloadIdentifier) = ^(id <ASImageContainerProtocol>imageContainer, NSError *error, id downloadIdentifier) {
__typeof__(self) strongSelf = weakSelf;
if (strongSelf == nil) {
return;
@ -390,9 +395,13 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
return;
}
if (responseImage != NULL) {
if (imageContainer != nil) {
strongSelf->_imageLoaded = YES;
strongSelf.image = responseImage;
if ([imageContainer asdk_animatedImageData] && _downloaderImplementsAnimatedImage) {
strongSelf.animatedImage = [_downloader animatedImageWithData:[imageContainer asdk_animatedImageData]];
} else {
strongSelf.image = [imageContainer asdk_image];
}
}
strongSelf->_downloadIdentifier = nil;
@ -402,7 +411,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
{
ASDN::MutexLocker l(strongSelf->_lock);
if (responseImage != NULL) {
if (imageContainer != nil) {
[strongSelf->_delegate imageNode:strongSelf didLoadImage:strongSelf.image];
}
else if (error && _delegateSupportsDidFailWithError) {
@ -415,16 +424,16 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
NSUUID *cacheUUID = [NSUUID UUID];
_cacheUUID = cacheUUID;
void (^cacheCompletion)(UIImage *) = ^(UIImage *image) {
void (^cacheCompletion)(id <ASImageContainerProtocol>) = ^(id <ASImageContainerProtocol> imageContainer) {
// If the cache UUID changed, that means this request was cancelled.
if (![_cacheUUID isEqual:cacheUUID]) {
return;
}
if (image == NULL && _downloader != nil) {
if ([imageContainer asdk_image] == NULL && _downloader != nil) {
[self _downloadImageWithCompletion:finished];
} else {
finished(image, NULL, nil);
finished(imageContainer, NULL, nil);
}
};

View File

@ -11,6 +11,7 @@
#import <AsyncDisplayKit/ASControlNode.h>
#import <AsyncDisplayKit/ASImageNode.h>
#import <AsyncDisplayKit/ASImageNode+AnimatedImage.h>
#import <AsyncDisplayKit/ASTextNode.h>
#import <AsyncDisplayKit/ASButtonNode.h>
#import <AsyncDisplayKit/ASMapNode.h>
@ -68,6 +69,7 @@
#import <AsyncDisplayKit/ASEqualityHelpers.h>
#import <AsyncDisplayKit/ASHighlightOverlayLayer.h>
#import <AsyncDisplayKit/ASIndexPath.h>
#import <AsyncDisplayKit/ASImageContainerProtocolCategories.h>
#import <AsyncDisplayKit/ASLog.h>
#import <AsyncDisplayKit/ASMutableAttributedStringBuilder.h>
#import <AsyncDisplayKit/ASThread.h>

View File

@ -0,0 +1,19 @@
//
// ASImageContainerProtocolCategories.h
// AsyncDisplayKit
//
// Created by Garrett Moon on 3/18/16.
// Copyright © 2016 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASImageProtocols.h"
@interface UIImage (ASImageContainerProtocol) <ASImageContainerProtocol>
@end
@interface NSData (ASImageContainerProtocol) <ASImageContainerProtocol>
@end

View File

@ -0,0 +1,37 @@
//
// ASImageContainerProtocolCategories.m
// AsyncDisplayKit
//
// Created by Garrett Moon on 3/18/16.
// Copyright © 2016 Facebook. All rights reserved.
//
#import "ASImageContainerProtocolCategories.h"
@implementation UIImage (ASImageContainerProtocol)
- (UIImage *)asdk_image
{
return self;
}
- (NSData *)asdk_animatedImageData
{
return nil;
}
@end
@implementation NSData (ASImageContainerProtocol)
- (UIImage *)asdk_image
{
return nil;
}
- (NSData *)asdk_animatedImageData
{
return self;
}
@end

View File

@ -11,7 +11,16 @@
NS_ASSUME_NONNULL_BEGIN
typedef void(^ASImageCacherCompletion)(UIImage * _Nullable imageFromCache);
@protocol ASAnimatedImageProtocol;
@protocol ASImageContainerProtocol <NSObject>
- (UIImage *)asdk_image;
- (NSData *)asdk_animatedImageData;
@end
typedef void(^ASImageCacherCompletion)(id <ASImageContainerProtocol> _Nullable imageFromCache);
@protocol ASImageCacheProtocol <NSObject>
@ -28,7 +37,7 @@ typedef void(^ASImageCacherCompletion)(UIImage * _Nullable imageFromCache);
the calling thread to fetch the image from a fast memory cache. It is OK to return nil from this method and instead
support only cachedImageWithURL:callbackQueue:completion: however, synchronous rendering will not be possible.
*/
- (nullable UIImage *)synchronouslyFetchedCachedImageWithURL:(NSURL *)URL;
- (nullable id <ASImageContainerProtocol>)synchronouslyFetchedCachedImageWithURL:(NSURL *)URL;
/**
@abstract Attempts to fetch an image with the given URL from the cache.
@ -52,7 +61,7 @@ typedef void(^ASImageCacherCompletion)(UIImage * _Nullable imageFromCache);
@end
typedef void(^ASImageDownloaderCompletion)(UIImage * _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier);
typedef void(^ASImageDownloaderCompletion)(id <ASImageContainerProtocol> _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier);
typedef void(^ASImageDownloaderProgress)(CGFloat progress);
typedef void(^ASImageDownloaderProgressImage)(UIImage *progressImage, id _Nullable downloadIdentifier);
@ -76,6 +85,12 @@ typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) {
@optional
/**
@abstract Return an object that conforms to ASAnimatedImageProtocol
@param animatedImageData Data that represents an animated image.
*/
- (nullable id <ASAnimatedImageProtocol>)animatedImageWithData:(NSData *)animatedImageData;
//You must implement the following method OR the deprecated method at the bottom
/**
@ -119,6 +134,27 @@ withDownloadIdentifier:(id)downloadIdentifier;
@end
@protocol ASAnimatedImageProtocol <NSObject>
@property (nonatomic, strong, readwrite) void (^coverImageReadyCallback)(UIImage *coverImage);
@required
@property (nonatomic, readonly) UIImage *coverImage;
@property (nonatomic, readonly) BOOL coverImageReady;
@property (nonatomic, readonly) CFTimeInterval totalDuration;
@property (nonatomic, readonly) NSUInteger frameInterval;
@property (nonatomic, readonly) size_t loopCount;
@property (nonatomic, readonly) size_t frameCount;
@property (nonatomic, readonly) BOOL playbackReady;
@property (nonatomic, strong, readwrite) dispatch_block_t playbackReadyCallback;
- (CGImageRef)imageAtIndex:(NSUInteger)index;
- (CFTimeInterval)durationAtIndex:(NSUInteger)index;
- (void)clearAnimatedImageCache;
@end
@protocol ASImageDownloaderProtocolDeprecated <ASImageDownloaderProtocol>
@optional

View File

@ -1,9 +1,9 @@
//
// ASPINRemoteImageDownloader.h
// Pods
// AsyncDisplayKit
//
// Created by Garrett Moon on 2/5/16.
//
// Copyright © 2016 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>

View File

@ -1,9 +1,9 @@
//
// ASPINRemoteImageDownloader.m
// Pods
// AsyncDisplayKit
//
// Created by Garrett Moon on 2/5/16.
//
// Copyright © 2016 Facebook. All rights reserved.
//
#ifdef PIN_REMOTE_IMAGE
@ -11,34 +11,104 @@
#import "ASAssert.h"
#import "ASThread.h"
#import "ASImageContainerProtocolCategories.h"
#if __has_include ("PINAnimatedImage.h")
#define PIN_ANIMATED_AVAILABLE 1
#import "PINAnimatedImage.h"
#import <PINRemoteImage/PINAlternateRepresentationProvider.h>
#else
#define PIN_ANIMATED_AVAILABLE 0
#endif
#import <PINRemoteImage/PINRemoteImageManager.h>
#import <PINRemoteImage/NSData+ImageDetectors.h>
#import <PINCache/PINCache.h>
#if PIN_ANIMATED_AVAILABLE
@interface ASPINRemoteImageDownloader () <PINRemoteImageManagerAlternateRepresentationProvider>
@end
@interface PINAnimatedImage (ASPINRemoteImageDownloader) <ASAnimatedImageProtocol>
@end
@implementation PINAnimatedImage (ASPINRemoteImageDownloader)
- (void)setCoverImageReadyCallback:(void (^)(UIImage * _Nonnull))coverImageReadyCallback
{
self.infoCompletion = coverImageReadyCallback;
}
- (void (^)(UIImage * _Nonnull))coverImageReadyCallback
{
return self.infoCompletion;
}
- (void)setPlaybackReadyCallback:(dispatch_block_t)playbackReadyCallback
{
self.fileReady = playbackReadyCallback;
}
- (dispatch_block_t)playbackReadyCallback
{
return self.fileReady;
}
@end
#endif
@implementation ASPINRemoteImageDownloader
+ (instancetype)sharedDownloader
{
static ASPINRemoteImageDownloader *sharedDownloader = nil;
static dispatch_once_t once = 0;
dispatch_once(&once, ^{
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
sharedDownloader = [[ASPINRemoteImageDownloader alloc] init];
});
return sharedDownloader;
}
- (PINRemoteImageManager *)sharedPINRemoteImageManager
{
static PINRemoteImageManager *sharedPINRemoteImageManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
#if PIN_ANIMATED_AVAILABLE
sharedPINRemoteImageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:nil alternativeRepresentationProvider:self];
#else
sharedPINRemoteImageManager = [[PINRemoteImageManager alloc] initWithSessionConfiguration:nil];
#endif
});
return sharedPINRemoteImageManager;
}
#pragma mark ASImageProtocols
- (UIImage *)synchronouslyFetchedCachedImageWithURL:(NSURL *)URL
#if PIN_ANIMATED_AVAILABLE
- (nullable id <ASAnimatedImageProtocol>)animatedImageWithData:(NSData *)animatedImageData
{
NSString *key = [[PINRemoteImageManager sharedImageManager] cacheKeyForURL:URL processorKey:nil];
PINRemoteImageManagerResult *result = [[PINRemoteImageManager sharedImageManager] synchronousImageFromCacheWithCacheKey:key options:PINRemoteImageManagerDownloadOptionsSkipDecode];
return [[PINAnimatedImage alloc] initWithAnimatedImageData:animatedImageData];
}
#endif
- (id <ASImageContainerProtocol>)synchronouslyFetchedCachedImageWithURL:(NSURL *)URL;
{
NSString *key = [[self sharedPINRemoteImageManager] cacheKeyForURL:URL processorKey:nil];
PINRemoteImageManagerResult *result = [[self sharedPINRemoteImageManager] synchronousImageFromCacheWithCacheKey:key options:PINRemoteImageManagerDownloadOptionsSkipDecode];
#if PIN_ANIMATED_AVAILABLE
if (result.alternativeRepresentation) {
return result.alternativeRepresentation;
}
#endif
return result.image;
}
- (void)fetchCachedImageWithURL:(NSURL *)URL
callbackQueue:(dispatch_queue_t)callbackQueue
completion:(void (^)(CGImageRef imageFromCache))completion
- (void)cachedImageWithURL:(NSURL *)URL
callbackQueue:(dispatch_queue_t)callbackQueue
completion:(ASImageCacherCompletion)completion
{
// We do not check the cache here and instead check it in downloadImageWithURL to avoid checking the cache twice.
// If we're targeting the main queue and we're on the main thread, complete immediately.
@ -53,23 +123,39 @@
- (void)clearFetchedImageFromCacheWithURL:(NSURL *)URL
{
PINRemoteImageManager *manager = [PINRemoteImageManager sharedImageManager];
PINRemoteImageManager *manager = [self sharedPINRemoteImageManager];
NSString *key = [manager cacheKeyForURL:URL processorKey:nil];
[[[manager cache] memoryCache] removeObjectForKey:key];
}
- (nullable id)downloadImageWithURL:(NSURL *)URL
callbackQueue:(dispatch_queue_t)callbackQueue
downloadProgress:(void (^)(CGFloat progress))downloadProgressBlock
completion:(void (^)(UIImage *image, NSError * error, id downloadIdentifier))completion
downloadProgress:(ASImageDownloaderProgress)downloadProgress
completion:(ASImageDownloaderCompletion)completion;
{
return [[PINRemoteImageManager sharedImageManager] downloadImageWithURL:URL options:PINRemoteImageManagerDownloadOptionsSkipDecode completion:^(PINRemoteImageManagerResult *result) {
return [[self sharedPINRemoteImageManager] downloadImageWithURL:URL options:PINRemoteImageManagerDownloadOptionsSkipDecode completion:^(PINRemoteImageManagerResult *result) {
/// If we're targeting the main queue and we're on the main thread, complete immediately.
if (ASDisplayNodeThreadIsMain() && callbackQueue == dispatch_get_main_queue()) {
completion(result.image, result.error, result.UUID);
#if PIN_ANIMATED_AVAILABLE
if (result.alternativeRepresentation) {
completion(result.alternativeRepresentation, result.error, result.UUID);
} else {
completion(result.image, result.error, result.UUID);
}
#else
completion(result.image, result.error, result.UUID);
#endif
} else {
dispatch_async(callbackQueue, ^{
#if PIN_ANIMATED_AVAILABLE
if (result.alternativeRepresentation) {
completion(result.alternativeRepresentation, result.error, result.UUID);
} else {
completion(result.image, result.error, result.UUID);
}
#else
completion(result.image, result.error, result.UUID);
#endif
});
}
}];
@ -78,7 +164,7 @@
- (void)cancelImageDownloadForIdentifier:(id)downloadIdentifier
{
ASDisplayNodeAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID");
[[PINRemoteImageManager sharedImageManager] cancelTaskWithUUID:downloadIdentifier];
[[self sharedPINRemoteImageManager] cancelTaskWithUUID:downloadIdentifier];
}
- (void)setProgressImageBlock:(ASImageDownloaderProgressImage)progressBlock callbackQueue:(dispatch_queue_t)callbackQueue withDownloadIdentifier:(id)downloadIdentifier
@ -86,13 +172,13 @@
ASDisplayNodeAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID");
if (progressBlock) {
[[PINRemoteImageManager sharedImageManager] setProgressImageCallback:^(PINRemoteImageManagerResult * _Nonnull result) {
[[self sharedPINRemoteImageManager] setProgressImageCallback:^(PINRemoteImageManagerResult * _Nonnull result) {
dispatch_async(callbackQueue, ^{
progressBlock(result.image, result.UUID);
});
} ofTaskWithUUID:downloadIdentifier];
} else {
[[PINRemoteImageManager sharedImageManager] setProgressImageCallback:nil ofTaskWithUUID:downloadIdentifier];
[[self sharedPINRemoteImageManager] setProgressImageCallback:nil ofTaskWithUUID:downloadIdentifier];
}
}
@ -114,7 +200,19 @@
pi_priority = PINRemoteImageManagerPriorityVeryHigh;
break;
}
[[PINRemoteImageManager sharedImageManager] setPriority:pi_priority ofTaskWithUUID:downloadIdentifier];
[[self sharedPINRemoteImageManager] setPriority:pi_priority ofTaskWithUUID:downloadIdentifier];
}
#pragma mark - PINRemoteImageManagerAlternateRepresentationProvider
- (id)alternateRepresentationWithData:(NSData *)data options:(PINRemoteImageManagerDownloadOptions)options
{
#if PIN_ANIMATED_AVAILABLE
if ([data pin_isGIF]) {
return data;
}
#endif
return nil;
}
@end

View File

@ -0,0 +1,17 @@
//
// ASWeakProxy.h
// AsyncDisplayKit
//
// Created by Garrett Moon on 4/12/16.
// Copyright © 2016 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface ASWeakProxy : NSObject
@property (nonatomic, weak, readonly) id target;
+ (instancetype)weakProxyWithTarget:(id)target;
@end

View File

@ -0,0 +1,31 @@
//
// ASWeakProxy.m
// AsyncDisplayKit
//
// Created by Garrett Moon on 4/12/16.
// Copyright © 2016 Facebook. All rights reserved.
//
#import "ASWeakProxy.h"
@implementation ASWeakProxy
- (instancetype)initWithTarget:(id)target
{
if (self = [super init]) {
_target = target;
}
return self;
}
+ (instancetype)weakProxyWithTarget:(id)target
{
return [[ASWeakProxy alloc] initWithTarget:target];
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
return _target;
}
@end

View File

@ -0,0 +1,27 @@
//
// ASImageNode+AnimatedImagePrivate.h
// AsyncDisplayKit
//
// Created by Garrett Moon on 3/30/16.
// Copyright © 2016 Facebook. All rights reserved.
//
#import "ASThread.h"
@interface ASImageNode ()
{
ASDN::RecursiveMutex _animatedImageLock;
ASDN::RecursiveMutex _animatedImagePausedLock;
ASDN::Mutex _displayLinkLock;
id <ASAnimatedImageProtocol> _animatedImage;
BOOL _animatedImagePaused;
CADisplayLink *_displayLink;
//accessed on main thread only
CFTimeInterval _playHead;
NSUInteger _playedLoops;
}
@property (atomic, assign) CFTimeInterval lastDisplayLinkFire;
@end

View File

@ -10,6 +10,7 @@
#import <AsyncDisplayKit/ASImageProtocols.h>
#import <AsyncDisplayKit/ASMultiplexImageNode.h>
#import <AsyncDisplayKit/ASImageContainerProtocolCategories.h>
#import <libkern/OSAtomic.h>

View File

@ -0,0 +1,17 @@
//
// AppDelegate.h
// ASAnimatedImage
//
// Created by Garrett Moon on 3/22/16.
// Copyright © 2016 Facebook, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@ -0,0 +1,45 @@
//
// AppDelegate.m
// ASAnimatedImage
//
// Created by Garrett Moon on 3/22/16.
// Copyright © 2016 Facebook, Inc. All rights reserved.
//
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end

View File

@ -0,0 +1,68 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,15 @@
//
// ViewController.h
// ASAnimatedImage
//
// Created by Garrett Moon on 3/22/16.
// Copyright © 2016 Facebook, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

View File

@ -0,0 +1,37 @@
//
// ViewController.m
// ASAnimatedImage
//
// Created by Garrett Moon on 3/22/16.
// Copyright © 2016 Facebook, Inc. All rights reserved.
//
#import "ViewController.h"
#import <AsyncDisplayKit/AsyncDisplayKit.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ASNetworkImageNode *imageNode = [[ASNetworkImageNode alloc] init];
imageNode.URL = [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/originals/07/44/38/074438e7c75034df2dcf37ba1057803e.gif"];
imageNode.frame = self.view.bounds;
imageNode.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
imageNode.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubnode:imageNode];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end

View File

@ -0,0 +1,16 @@
//
// main.m
// ASAnimatedImage
//
// Created by Garrett Moon on 3/22/16.
// Copyright © 2016 Facebook, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

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

View File

@ -0,0 +1,385 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
683ADBA31CA19883005863A4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 683ADBA21CA19883005863A4 /* main.m */; };
683ADBA61CA19883005863A4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 683ADBA51CA19883005863A4 /* AppDelegate.m */; };
683ADBA91CA19883005863A4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 683ADBA81CA19883005863A4 /* ViewController.m */; };
683ADBAC1CA19883005863A4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 683ADBAA1CA19883005863A4 /* Main.storyboard */; };
683ADBAE1CA19883005863A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 683ADBAD1CA19883005863A4 /* Assets.xcassets */; };
683ADBB11CA19883005863A4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 683ADBAF1CA19883005863A4 /* LaunchScreen.storyboard */; };
EE964E5E7CD506D45C6DCC49 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A6F2399FA1A86586D9BDAE05 /* libPods.a */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
683ADB9E1CA19883005863A4 /* ASAnimatedImage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ASAnimatedImage.app; sourceTree = BUILT_PRODUCTS_DIR; };
683ADBA21CA19883005863A4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
683ADBA41CA19883005863A4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
683ADBA51CA19883005863A4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
683ADBA71CA19883005863A4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
683ADBA81CA19883005863A4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
683ADBAB1CA19883005863A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
683ADBAD1CA19883005863A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
683ADBB01CA19883005863A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
683ADBB21CA19883005863A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A6F2399FA1A86586D9BDAE05 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
BBB395EF2813E7DB5CB49459 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
BBBE85D30A6D31AD7021A9AF /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
683ADB9B1CA19883005863A4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
EE964E5E7CD506D45C6DCC49 /* libPods.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
683ADB951CA19883005863A4 = {
isa = PBXGroup;
children = (
683ADBA01CA19883005863A4 /* ASAnimatedImage */,
683ADB9F1CA19883005863A4 /* Products */,
71A772B0DB9B7760CE330DD9 /* Pods */,
8C6AC07DE55B51935C632F56 /* Frameworks */,
);
sourceTree = "<group>";
};
683ADB9F1CA19883005863A4 /* Products */ = {
isa = PBXGroup;
children = (
683ADB9E1CA19883005863A4 /* ASAnimatedImage.app */,
);
name = Products;
sourceTree = "<group>";
};
683ADBA01CA19883005863A4 /* ASAnimatedImage */ = {
isa = PBXGroup;
children = (
683ADBA41CA19883005863A4 /* AppDelegate.h */,
683ADBA51CA19883005863A4 /* AppDelegate.m */,
683ADBA71CA19883005863A4 /* ViewController.h */,
683ADBA81CA19883005863A4 /* ViewController.m */,
683ADBAA1CA19883005863A4 /* Main.storyboard */,
683ADBAD1CA19883005863A4 /* Assets.xcassets */,
683ADBAF1CA19883005863A4 /* LaunchScreen.storyboard */,
683ADBB21CA19883005863A4 /* Info.plist */,
683ADBA11CA19883005863A4 /* Supporting Files */,
);
path = ASAnimatedImage;
sourceTree = "<group>";
};
683ADBA11CA19883005863A4 /* Supporting Files */ = {
isa = PBXGroup;
children = (
683ADBA21CA19883005863A4 /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
71A772B0DB9B7760CE330DD9 /* Pods */ = {
isa = PBXGroup;
children = (
BBBE85D30A6D31AD7021A9AF /* Pods.debug.xcconfig */,
BBB395EF2813E7DB5CB49459 /* Pods.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
8C6AC07DE55B51935C632F56 /* Frameworks */ = {
isa = PBXGroup;
children = (
A6F2399FA1A86586D9BDAE05 /* libPods.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
683ADB9D1CA19883005863A4 /* ASAnimatedImage */ = {
isa = PBXNativeTarget;
buildConfigurationList = 683ADBB51CA19883005863A4 /* Build configuration list for PBXNativeTarget "ASAnimatedImage" */;
buildPhases = (
694B306B43ED1C3916B0D909 /* Check Pods Manifest.lock */,
683ADB9A1CA19883005863A4 /* Sources */,
683ADB9B1CA19883005863A4 /* Frameworks */,
683ADB9C1CA19883005863A4 /* Resources */,
26A96BEEF893B1FA39F144CF /* Embed Pods Frameworks */,
2ADE0E7B5309A9CD043DDB3E /* Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = ASAnimatedImage;
productName = ASAnimatedImage;
productReference = 683ADB9E1CA19883005863A4 /* ASAnimatedImage.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
683ADB961CA19883005863A4 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0720;
ORGANIZATIONNAME = "Facebook, Inc.";
TargetAttributes = {
683ADB9D1CA19883005863A4 = {
CreatedOnToolsVersion = 7.2;
};
};
};
buildConfigurationList = 683ADB991CA19883005863A4 /* Build configuration list for PBXProject "ASAnimatedImage" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 683ADB951CA19883005863A4;
productRefGroup = 683ADB9F1CA19883005863A4 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
683ADB9D1CA19883005863A4 /* ASAnimatedImage */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
683ADB9C1CA19883005863A4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
683ADBB11CA19883005863A4 /* LaunchScreen.storyboard in Resources */,
683ADBAE1CA19883005863A4 /* Assets.xcassets in Resources */,
683ADBAC1CA19883005863A4 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
26A96BEEF893B1FA39F144CF /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
2ADE0E7B5309A9CD043DDB3E /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
showEnvVarsInLog = 0;
};
694B306B43ED1C3916B0D909 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
683ADB9A1CA19883005863A4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
683ADBA91CA19883005863A4 /* ViewController.m in Sources */,
683ADBA61CA19883005863A4 /* AppDelegate.m in Sources */,
683ADBA31CA19883005863A4 /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
683ADBAA1CA19883005863A4 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
683ADBAB1CA19883005863A4 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
683ADBAF1CA19883005863A4 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
683ADBB01CA19883005863A4 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
683ADBB31CA19883005863A4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
683ADBB41CA19883005863A4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
683ADBB61CA19883005863A4 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = BBBE85D30A6D31AD7021A9AF /* Pods.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = ASAnimatedImage/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = facebook.ASAnimatedImage;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
683ADBB71CA19883005863A4 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = BBB395EF2813E7DB5CB49459 /* Pods.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = ASAnimatedImage/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = facebook.ASAnimatedImage;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
683ADB991CA19883005863A4 /* Build configuration list for PBXProject "ASAnimatedImage" */ = {
isa = XCConfigurationList;
buildConfigurations = (
683ADBB31CA19883005863A4 /* Debug */,
683ADBB41CA19883005863A4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
683ADBB51CA19883005863A4 /* Build configuration list for PBXNativeTarget "ASAnimatedImage" */ = {
isa = XCConfigurationList;
buildConfigurations = (
683ADBB61CA19883005863A4 /* Debug */,
683ADBB71CA19883005863A4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 683ADB961CA19883005863A4 /* Project object */;
}

View File

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

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "683ADB9D1CA19883005863A4"
BuildableName = "ASAnimatedImage.app"
BlueprintName = "ASAnimatedImage"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "683ADB9D1CA19883005863A4"
BuildableName = "ASAnimatedImage.app"
BlueprintName = "ASAnimatedImage"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "683ADB9D1CA19883005863A4"
BuildableName = "ASAnimatedImage.app"
BlueprintName = "ASAnimatedImage"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "683ADB9D1CA19883005863A4"
BuildableName = "ASAnimatedImage.app"
BlueprintName = "ASAnimatedImage"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

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