From 16549a908de7ceb414070dabea244237b31e6da5 Mon Sep 17 00:00:00 2001 From: Jerome Morissard Date: Thu, 14 May 2015 11:46:14 +0200 Subject: [PATCH 1/3] Improve doc, Fix retain cycle --- JMAnimatedImageView.podspec | 4 +- .../JMAnimatedImageView+Image.h | 13 +++ .../JMAnimatedImageView/JMAnimatedImageView.h | 48 ++++++++++ .../JMAnimatedImageView/JMAnimatedImageView.m | 29 +++--- .../JMAnimationOperation.h | 10 +- .../JMAnimatedImageView/JMGif.h | 6 +- .../JMAnimatedImageView/JMGif.m | 94 +++++++++++++++++-- .../JMAnimatedImageView/UIImage+JM.h | 25 +++++ README.md | 26 ++++- 9 files changed, 233 insertions(+), 22 deletions(-) diff --git a/JMAnimatedImageView.podspec b/JMAnimatedImageView.podspec index f83bc31..3856443 100644 --- a/JMAnimatedImageView.podspec +++ b/JMAnimatedImageView.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'JMAnimatedImageView' - s.version = '0.2.2' + s.version = '0.2.4' s.requires_arc = true s.author = { 'Morissard Jérome' => 'morissardj@gmail.com' @@ -11,7 +11,7 @@ Pod::Spec.new do |s| s.homepage = 'https://github.com/leverdeterre/JMAnimatedImageView' s.source = { :git => 'https://github.com/leverdeterre/JMAnimatedImageView.git', - :tag => "0.2.2" + :tag => "0.2.4" } s.source_files = 'JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/*' end diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView+Image.h b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView+Image.h index 803b3d2..27cd721 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView+Image.h +++ b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView+Image.h @@ -10,7 +10,20 @@ @interface JMAnimatedImageView (Image) +/** + * imageAtIndex: This method help to get the image for an index + * + * @param index NSInteger + * + * @return UIImage image + */ - (UIImage *)imageAtIndex:(NSInteger)index; + +/** + * numberOfImages. This method return the number of images + * + * @return NSUInteger numberOfImages + */ - (NSUInteger)numberOfImages; @end diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView.h b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView.h index adb3fc0..0a520a5 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView.h +++ b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView.h @@ -43,19 +43,67 @@ typedef void (^JMCompletionFinishBlock)(BOOL resul); @property (assign, nonatomic) JMAnimatedImageViewOrder imageOrder; @property (assign, nonatomic) BOOL interactiveAnimation; +/** + * reloadAnimationImages, This method will call animationDatasource + */ - (void)reloadAnimationImages; +/** + * setCurrentIndex, This method will animate the modification of image + * + * @param index destination index + * @param animated BOOL animated + */ - (void)setCurrentIndex:(NSInteger)index animated:(BOOL)animated; + +/** + * setImage, This method will force the image to the index + * + * @param img UIImage + * @param index NSInteger index + */ - (void)setImage:(UIImage *)img forCurrentIndex:(NSInteger)index; +/** + * animateToIndex:withDuration:, This method will animate the modification of images to access to the index in parameter. + * + * @param index NSInteger destination index + * @param duration NSTimeInterval duration + */ - (void)animateToIndex:(NSInteger)index withDuration:(NSTimeInterval)duration; + +/** + * animateToIndex:withDuration:withCompletionBlock:, This method will animate the modification of images to access to the index in parameter. + * + * @param index NSInteger destination index + * @param duration NSTimeInterval duration + * @param finishBlock JMCompletionFinishBlock CompletionBlock + */ - (void)animateToIndex:(NSInteger)index withDuration:(NSTimeInterval)duration withCompletionBlock:(JMCompletionFinishBlock)finishBlock; //Specific to GIF @property (strong, readonly, nonatomic) JMGif *gifObject; +/** + * isAGifImageView + * + * @return BOOL + */ - (BOOL)isAGifImageView; + +/** + * reloadAnimationImagesFromGifData:, This method reload a GIF image from a GIF NSData + * + * @param data NSData data + */ - (void)reloadAnimationImagesFromGifData:(NSData *)data; +- (void)reloadAnimationImagesFromGifData:(NSData *)data fromUrl:(NSURL *)url; + +/** + * reloadAnimationImagesFromGifNamed:, This method reload a GIF image from a GIF named + * + * @param gitName NSString gitName + */ - (void)reloadAnimationImagesFromGifNamed:(NSString *)gitName; @end diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView.m b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView.m index bc05e6f..ad63956 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView.m +++ b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView.m @@ -81,6 +81,13 @@ - (void)reloadAnimationImages } } +- (void)reloadAnimationImagesFromGifData:(NSData *)data fromUrl:(NSURL *)url +{ + _gifObject = [[JMGif alloc] initWithData:data fromURL:url]; + self.animationDuration = JMDefaultGifDuration; + [self setCurrentCardImageAtindex:0]; +} + - (void)reloadAnimationImagesFromGifData:(NSData *)data { _gifObject = [[JMGif alloc] initWithData:data]; @@ -301,7 +308,7 @@ - (void)imageViewTouchedWithPanGesture:(UIPanGestureRecognizer *)gestureRecogniz NSInteger pointUnity = self.frame.size.width / [self numberOfImages]; //Compute inerty using velocity - NSInteger shift = abs(velocity.x) / (16 * [UIScreen mainScreen].scale * pointUnity); + NSInteger shift = fabs(velocity.x) / (16 * [UIScreen mainScreen].scale * pointUnity); if(velocity.x > 0) { [self setCurrentCardImageAtindex:index+(_imageOrder) * shift]; @@ -390,16 +397,16 @@ - (void)moveCurrentCardImageFromIndex:(NSInteger)fromIndex { dispatch_async(self.animationManagementQueue, ^{ NSTimeInterval unitDuration; - NSInteger shiftUnit = shift / abs(shift); // 1 ou -1 + NSInteger shiftUnit = shift / abs((int)shift); // 1 ou -1 if (duration == JMDefaultGifDuration) { unitDuration = duration; } else { if (option == UIImageViewAnimationOptionLinear) { - unitDuration = duration / abs(shift); + unitDuration = duration / abs((int)shift); } else { - unitDuration = duration / abs(shift * shift); + unitDuration = duration / abs((int)(shift * shift)); } } @@ -424,28 +431,28 @@ - (void)moveCurrentCardImageFromIndex:(NSInteger)fromIndex if ([self isAGifImageView]) { JMGifItem *item = [[self.gifObject items] objectAtIndex:index]; - NSNumber *delay = [item.delay objectForKey:JMGifItemDelayTimeKey]; - currentInterval = [delay doubleValue]; + currentInterval = [item delayDuration]; } + __weak JMAnimatedImageView *weakSelf = self; JMAnimationOperation *operation = [JMAnimationOperation animationOperationWithDuration:currentInterval completion:^(BOOL finished) { - if (self.animationType == JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition) { - if ([self operationQueueIsFinished] == YES) { + if (weakSelf.animationType == JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition) { + if ([weakSelf operationQueueIsFinished] == YES) { if (finishBlock) { finishBlock(YES); } - if (self.animationRepeatCount == 0 && self.animationState == UIImageViewAnimationStateInPgrogress) { - [self continueAnimating]; + if (weakSelf.animationRepeatCount == 0 && weakSelf.animationState == UIImageViewAnimationStateInPgrogress) { + [weakSelf continueAnimating]; } } } }]; - operation.animatedImageView = self; + operation.animatedImageView = weakSelf; operation.imageIndex = index; currentInterval = 0; diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimationOperation.h b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimationOperation.h index 4da2f95..2d1e285 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimationOperation.h +++ b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMAnimationOperation.h @@ -19,7 +19,15 @@ typedef void (^JMAnimationBlock)(void); @property (assign, nonatomic) NSInteger imageIndex; @property (weak, nonatomic) JMAnimatedImageView *animatedImageView; +/** + * animationOperationWithDuration:completion: create an animated operation, JMAnimationOperation + * + * @param duration NSTimeInterval duration + * @param completion JMCompletionBlock completionBlock + * + * @return JMAnimationOperation + */ + (instancetype)animationOperationWithDuration:(NSTimeInterval)duration - completion:(void (^)(BOOL finished))completion; + completion:(JMCompletionBlock)completion; @end diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMGif.h b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMGif.h index e98122c..c3f1244 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMGif.h +++ b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMGif.h @@ -8,9 +8,12 @@ #import @interface JMGif : NSObject + @property (readonly, nonatomic) NSArray *items; //images + infos +@property (readonly, nonatomic) NSURL *url; - (instancetype)initWithData:(NSData *)data; +- (instancetype)initWithData:(NSData *)data fromURL:(NSURL *)url; + (instancetype)gifNamed:(NSString *)gifName; - (UIImage *)imageAtIndex:(NSInteger)index; @@ -19,6 +22,7 @@ + (BOOL)cleanGifCacheError:(NSError **)error; + (BOOL)cleanGifCacheForGifNamed:(NSString *)gifName; + (BOOL)cleanGifCacheForGifNamed:(NSString *)gifName error:(NSError **)error; ++ (void)cacheGifData:(NSData *)data gifAbsoluteUrl:(NSString *)absoluteUrl; @end @@ -31,7 +35,7 @@ @property (readonly, nonatomic) UIImage *image; @property (readonly, nonatomic) NSString *imagePath; -@property (readonly, nonatomic) NSDictionary *delay; +@property (readonly, nonatomic) NSTimeInterval delayDuration; - (instancetype)initWithImage:(UIImage *)image frameProperties:(NSDictionary *)frameProperties; - (instancetype)initWithImagePath:(NSString *)imagePath frameProperties:(NSDictionary *)frameProperties; diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMGif.m b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMGif.m index a63eb07..49bb741 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMGif.m +++ b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/JMGif.m @@ -14,20 +14,32 @@ #import #import "JMAmimatedImageViewMacro.h" +@interface JMGif () +@end + @implementation JMGif -- (instancetype)initWithData:(NSData *)data gifName:(NSString *)gifName +- (instancetype)initWithData:(NSData *)data gifName:(NSString *)gifName fromURL:(NSURL *)url { self = [super init]; if (self) { - [self loadGifWithData:data gifName:gifName]; + if (url.absoluteString.length && data) { + [self.class cacheGifData:data gifAbsoluteUrl:url.absoluteString]; + } + + [self loadGifWithData:data gifName:gifName fromURL:url]; } return self; } - (instancetype)initWithData:(NSData *)data { - return [self initWithData:data gifName:nil]; + return [self initWithData:data gifName:nil fromURL:nil]; +} + +- (instancetype)initWithData:(NSData *)data fromURL:(NSURL *)url +{ + return [self initWithData:data gifName:nil fromURL:url]; } + (instancetype)gifNamed:(NSString *)gifName @@ -36,14 +48,54 @@ + (instancetype)gifNamed:(NSString *)gifName NSURL *url = [[NSBundle mainBundle] URLForResource:gifName withExtension:@"gif"]; NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error]; if (nil == error) { - JMGif *gif = [[JMGif alloc] initWithData:data gifName:gifName]; + JMGif *gif = [[JMGif alloc] initWithData:data gifName:gifName fromURL:nil]; return gif; } return nil; } -- (void)loadGifWithData:(NSData *)data gifName:(NSString *)gifName ++ (void)cacheGifData:(NSData *)data gifAbsoluteUrl:(NSString *)absoluteUrl +{ + CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); + + if (!imageSource) { + JMOLog(@"Error: Failed to `CGImageSourceCreateWithData` for animated GIF data %@", data); + return; + } + + // Early return if not GIF! + CFStringRef imageSourceContainerType = CGImageSourceGetType(imageSource); + if (!UTTypeConformsTo(imageSourceContainerType, kUTTypeGIF)) { + JMOLog(@"Error: Supplied data is of type %@ and doesn't seem to be GIF data %@", imageSourceContainerType, data); + CFRelease(imageSource); + return; + } + + // Iterate through frame images + size_t imageCount = CGImageSourceGetCount(imageSource); + for (size_t i = 0; i < imageCount; i++) { + CGImageRef frameImageRef = CGImageSourceCreateImageAtIndex(imageSource, i, NULL); + if (frameImageRef) { + //UIImage *frameImage = [UIImage imageWithCGImage:frameImageRef]; + // Check for valid `frameImage` before parsing its properties as frames can be corrupted (and `frameImage` even `nil` when `frameImageRef` was valid). + if (YES) { + NSDictionary *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(imageSource, i, NULL); + NSDictionary *framePropertiesGIF = [frameProperties objectForKey:(id)kCGImagePropertyGIFDictionary]; + if (absoluteUrl) { + if ([self gifNamedAlreadyCached:absoluteUrl index:i] == NO) { + [self cacheGifName:absoluteUrl image:[UIImage imageWithCGImage:frameImageRef] representingIndex:i]; + } + } + } + + CFRelease(frameImageRef); + } + } + CFRelease(imageSource); +} + +- (void)loadGifWithData:(NSData *)data gifName:(NSString *)gifName fromURL:(NSURL *)url { CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); @@ -89,7 +141,16 @@ - (void)loadGifWithData:(NSData *)data gifName:(NSString *)gifName if ([self.class gifNamedAlreadyCached:gifName index:i] == NO) { [self.class cacheGifName:gifName image:[UIImage imageWithCGImage:frameImageRef] representingIndex:i]; } + + } else if (url.absoluteString) { + item = [[JMGifItem alloc] initWithImagePath:[self.class imagePathForeGifName:url.absoluteString index:i] + frameProperties:framePropertiesGIF]; + if ([self.class gifNamedAlreadyCached:url.absoluteString index:i] == NO) { + [self.class cacheGifName:url.absoluteString image:[UIImage imageWithCGImage:frameImageRef] representingIndex:i]; + } + } else { + NSLog(@"Loading full UIImage ..."); item = [[JMGifItem alloc] initWithImage:[UIImage imageWithCGImage:frameImageRef] frameProperties:framePropertiesGIF]; } @@ -172,7 +233,7 @@ + (BOOL)cleanGifCacheForGifNamed:(NSString *)gifName error:(NSError **)error + (NSString *)imagePathForeGifName:(NSString *)gifName index:(NSInteger)index { NSString *directoryPath = [NSString stringWithFormat:@"%@/%@",[self cacheDirectoryPath],gifName]; - NSString *filePath = [NSString stringWithFormat:@"%@/%d.png",directoryPath,index]; + NSString *filePath = [NSString stringWithFormat:@"%@/%ld.png",directoryPath,(long)index]; return filePath; } @@ -201,8 +262,29 @@ + (void)cacheGifName:(NSString *)gifName image:(UIImage *)img representingIndex: @end +@interface JMGifItem () +@property (readonly, nonatomic) NSDictionary *delay; +@end + @implementation JMGifItem +- (NSTimeInterval)delayDuration +{ + NSNumber *delay = [_delay objectForKey:JMGifItemUnclampedDelayTimeKey]; + if (nil == delay) { + delay = [_delay objectForKey:JMGifItemDelayTimeKey]; + } + + NSTimeInterval valueToReturn = [delay doubleValue]; + if (valueToReturn < 0.011f) { + // a duration of <= 10 ms. See and + // for more information. + valueToReturn = 0.100f; + } + + return valueToReturn; +} + - (instancetype)initWithImage:(UIImage *)image frameProperties:(NSDictionary *)frameProperties { return [self initWithImage:image imagePath:nil frameProperties:frameProperties]; diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/UIImage+JM.h b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/UIImage+JM.h index 47ceb8a..1785231 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/UIImage+JM.h +++ b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView/UIImage+JM.h @@ -11,8 +11,33 @@ @interface UIImage (JM) +/** + * jm_imageNamed:, This method return an UIImage for a imageName, using default system cache + * + * @param name NSString, image name + * + * @return UIImage + */ + (UIImage *)jm_imageNamed:(NSString *)name; + +/** + * jm_imageNamed:withOption:, This method return an UIImage for a imageName, using a specific MemoryOption + * + * @param name NSString, image name + * @param option JMAnimatedImageViewMemoryOption option + * + * @return UIImage + */ + (UIImage *)jm_imageNamed:(NSString *)name withOption:(JMAnimatedImageViewMemoryOption)option; + +/** + * jm_imagePath:withOption:, This method return an UIImage for a imagePath, using a specific MemoryOption + * + * @param imagePath NSString, image path + * @param option JMAnimatedImageViewMemoryOption option + * + * @return UIImage + */ + (UIImage *)jm_imagePath:(NSString *)imagePath withOption:(JMAnimatedImageViewMemoryOption)option; @end diff --git a/README.md b/README.md index f3a3741..d8b2be8 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,16 @@ JMAnimatedImageView is a performant subclass of UIImageView: - Can use has a Carousel, - GIF are supported to load your animations. -## Installation & Usage +## Change Log + +0.2.4 : + +- Improve documentation +- Fix retain cycle (Thanks Instruments!) +- JMGif allocation for a better integration with your favorites network libraries (initWithData:(NSData *)data fromURL:(NSURL *)url;) + + +## Installation Simply replace your `UIImageView` instances with instances of `JMAnimatedImageView`. @@ -18,6 +27,9 @@ If using CocoaPods, the quickest way to try it out is to type this on the comman $ pod try JMAnimatedImageView ``` +## Usage +### For a local animation from files into bundle + In your code, `#import "JMAnimatedImageView.h"` and `#import "JMAnimatedImageView.h"` ```objective-c @@ -40,6 +52,18 @@ self.jmImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinear self.jmImageView.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; ``` +### For a remote Gif + +```objective-c +@property (weak, nonatomic) IBOutlet JMAnimatedImageView *jmImageView; + +[[JMApi sharedApi] downloadYourGifFileHasData:^(NSData *gifData) { + self.animatedImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; + self.animatedImageView.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; + [self.animatedImageView reloadAnimationImagesFromGifData:gifData fromUrl:url]; + [self.animatedImageView startAnimating]; +}]; +``` Some parameters : From 9019b9e7a714894106e616b29ba9e990ea6bfa5a Mon Sep 17 00:00:00 2001 From: Jerome Morissard Date: Thu, 14 May 2015 14:32:38 +0200 Subject: [PATCH 2/3] Improve demo structrure --- .../JMAnimatedImageView/JMFLViewController.m | 72 ++++++++-------- .../JMTableViewController.h | 18 ++-- .../JMTableViewController.m | 85 ++++++++++++------- .../JMAnimatedImageView/JMViewController.m | 56 ++++++++++-- 4 files changed, 149 insertions(+), 82 deletions(-) diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMFLViewController.m b/JMAnimatedImageView/JMAnimatedImageView/JMFLViewController.m index ccfe680..2ce15c5 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMFLViewController.m +++ b/JMAnimatedImageView/JMAnimatedImageView/JMFLViewController.m @@ -23,46 +23,46 @@ - (void)viewDidLoad // Do any additional setup after loading the view from its nib. self.title = @"3 GIF, 3 animations ..."; - /* - JMDemoGIFAutomaticAnimationUsingImageViewImageAndSystemCache, - JMDemoGIFInteractiveAnimationUsingImageViewImageAndSystemCache, - JMDemoGIFMultipleAnimationUsingImageViewImageAndSystemCache - */ - - if (self.demoExemple == JMDemoGIFAutomaticAnimationUsingImageViewImageAndSystemCache) { - NSURL *url = [[NSBundle mainBundle] URLForResource:@"rock" withExtension:@"gif"]; - NSData *data = [NSData dataWithContentsOfURL:url]; - [self.carImageView1 reloadAnimationImagesFromGifData:data]; - self.carImageView1.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; - self.carImageView1.animationDuration = 3; - [self.carImageView1 startAnimating]; - - url = [[NSBundle mainBundle] URLForResource:@"Rotating_earth" withExtension:@"gif"]; - data = [NSData dataWithContentsOfURL:url]; - [self.carImageView2 reloadAnimationImagesFromGifData:data]; - self.carImageView2.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; - self.carImageView2.animationDuration = 3; - [self.carImageView2 startAnimating]; - - url = [[NSBundle mainBundle] URLForResource:@"nyan" withExtension:@"gif"]; - data = [NSData dataWithContentsOfURL:url]; - [self.carImageView3 reloadAnimationImagesFromGifData:data]; - self.carImageView3.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; - [self.carImageView3 startAnimating]; - - } else if (self.demoExemple == JMDemoGIFInteractiveAnimationUsingImageViewImageAndSystemCache) { - - [self.carImageView1 reloadAnimationImagesFromGifNamed:@"rock"]; - self.carImageView1.animationType = JMAnimatedImageViewAnimationTypeInteractive; - [self.carImageView1 setInteractiveAnimation:YES]; - [self.carImageView2 reloadAnimationImagesFromGifNamed:@"Rotating_earth"]; - self.carImageView2.animationType = JMAnimatedImageViewAnimationTypeInteractive; - [self.carImageView2 setInteractiveAnimation:YES]; + NSURL *url = [[NSBundle mainBundle] URLForResource:@"rock" withExtension:@"gif"]; + NSData *data = [NSData dataWithContentsOfURL:url]; + [self.carImageView1 reloadAnimationImagesFromGifData:data]; + self.carImageView1.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; + self.carImageView1.animationDuration = 3; + [self.carImageView1 reloadAnimationImagesFromGifNamed:@"rock"]; - [self.carImageView3 reloadAnimationImagesFromGifNamed:@"nyan"]; + url = [[NSBundle mainBundle] URLForResource:@"Rotating_earth" withExtension:@"gif"]; + data = [NSData dataWithContentsOfURL:url]; + [self.carImageView2 reloadAnimationImagesFromGifData:data]; + self.carImageView2.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; + self.carImageView2.animationDuration = 3; + [self.carImageView2 reloadAnimationImagesFromGifNamed:@"Rotating_earth"]; + + url = [[NSBundle mainBundle] URLForResource:@"nyan" withExtension:@"gif"]; + data = [NSData dataWithContentsOfURL:url]; + [self.carImageView3 reloadAnimationImagesFromGifData:data]; + self.carImageView3.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; + [self.carImageView3 reloadAnimationImagesFromGifNamed:@"nyan"]; + + if (self.demoExemple & JMDemoInteractive) { + + self.carImageView1.animationType = JMAnimatedImageViewAnimationTypeInteractive; + self.carImageView2.animationType = JMAnimatedImageViewAnimationTypeInteractive; self.carImageView3.animationType = JMAnimatedImageViewAnimationTypeInteractive; + [self.carImageView1 setInteractiveAnimation:YES]; + [self.carImageView2 setInteractiveAnimation:YES]; [self.carImageView3 setInteractiveAnimation:YES]; + + } else { + self.carImageView1.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; + self.carImageView2.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; + self.carImageView3.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; + [self.carImageView1 setInteractiveAnimation:NO]; + [self.carImageView2 setInteractiveAnimation:NO]; + [self.carImageView3 setInteractiveAnimation:NO]; + [self.carImageView1 startAnimating]; + [self.carImageView2 startAnimating]; + [self.carImageView3 startAnimating]; } } diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMTableViewController.h b/JMAnimatedImageView/JMAnimatedImageView/JMTableViewController.h index 0eac3a9..9a7ec1c 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMTableViewController.h +++ b/JMAnimatedImageView/JMAnimatedImageView/JMTableViewController.h @@ -8,15 +8,15 @@ #import -typedef NS_ENUM(NSUInteger, JMDemoType) { - JMDemoAutomaticAnimationUsingImageViewImageAndSystemCache = 0, - JMDemoAutomaticAnimationUsingJMAnimatedImageViewImageAndSystemCache, - JMDemoAutomaticAnimationUsingJMAnimatedImageViewImageAndWithoutCache, - JMDemoAutoSwipeAnimationUsingJMAnimatedImageViewImageAndWithoutCache, - JMDemoInteractiveAnimationUsingJMAnimatedImageViewImageAndWithoutCache, - JMDemoCarouselUsingJMAnimatedImageViewImageAndWithoutCache, - JMDemoGIFAutomaticAnimationUsingImageViewImageAndSystemCache, - JMDemoGIFInteractiveAnimationUsingImageViewImageAndSystemCache +typedef NS_OPTIONS(NSUInteger, JMDemoType) { + JMDemoAutomatic = 1, + JMDemoInteractive = 1 << 1, + JMDemoChangeImageSwipeTransition = 1 << 2, + JMDemoChangeImageNoTransition = 1 << 3, + JMDemoMemoryBySystem = 1 << 4, + JMDemoMemoryByMyComponent = 1 << 5, + JMDemoReverseImage = 1 << 6, + JMDemoPhotos = 1 << 8 }; @interface JMTableViewController : UITableViewController diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMTableViewController.m b/JMAnimatedImageView/JMAnimatedImageView/JMTableViewController.m index 7de65b7..e3819cc 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMTableViewController.m +++ b/JMAnimatedImageView/JMAnimatedImageView/JMTableViewController.m @@ -50,7 +50,7 @@ - (void)viewDidAppear:(BOOL)animated - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return 8; + return 7; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath @@ -58,55 +58,44 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N JMTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"JMTableViewCell" forIndexPath:indexPath]; switch (indexPath.row) { - case JMDemoAutomaticAnimationUsingImageViewImageAndSystemCache: - cell.jmLabel.text = @"AUTOMATIC ANIMATION : using UIImageView"; + case 0: + cell.jmLabel.text = @"PNG + Automatic Transition + system cache"; cell.jmDetailsLabel.text = @"All images are loaded in one time in memory (so ... it's take a lot of time to run the 1st time)."; break; - case JMDemoAutomaticAnimationUsingJMAnimatedImageViewImageAndSystemCache: - cell.jmLabel.text = @"AUTOMATIC ANIMATION : using JMAnimatedImageView (using Sytem cache)"; + case 1: + cell.jmLabel.text = @"PNG + Automatic Transition + system cache"; cell.jmDetailsLabel.text = @"Images are loaded during the animation."; break; - case JMDemoAutomaticAnimationUsingJMAnimatedImageViewImageAndWithoutCache: - cell.jmLabel.text = @"AUTOMATIC ANIMATION : using JMAnimatedImageView (Low memory usage)"; + case 2: + cell.jmLabel.text = @"PNG + Automatic Transition + JMAnimatedImageView cache"; cell.jmDetailsLabel.text = @"More CPU time to load / reload images but less memory used."; break; - case JMDemoAutoSwipeAnimationUsingJMAnimatedImageViewImageAndWithoutCache: - cell.jmLabel.text = @"AUTOMATIC ANIMATION : using JMAnimatedImageView with transition"; - cell.jmDetailsLabel.text = @"More CPU time to load / reload images but less memory used."; - break; - - case JMDemoInteractiveAnimationUsingJMAnimatedImageViewImageAndWithoutCache: - cell.jmLabel.text = @"INTERACTIVE ANIMATION : using JMAnimatedImageView (Low memory usage)"; + case 3: + cell.jmLabel.text = @"PNG + Interactive Transition + JMAnimatedImageView cache"; cell.jmDetailsLabel.text = @"Swipe left / Right to manage the animation."; break; - case JMDemoCarouselUsingJMAnimatedImageViewImageAndWithoutCache: - cell.jmLabel.text = @"SIMPLE CAROUSEL : using JMAnimatedImageView (Low memory usage)"; - cell.jmDetailsLabel.text = @"Swipe left / Right"; + case 4: + cell.jmLabel.text = @"PNG + Carousel Transition + JMAnimatedImageView cache"; + cell.jmDetailsLabel.text = @"Swipe left / Right to swipe"; break; - case JMDemoGIFAutomaticAnimationUsingImageViewImageAndSystemCache: - cell.jmLabel.text = @"GIF ANIMATION : using JMAnimatedImageView (Low memory usage)"; + case 5: + cell.jmLabel.text = @"GIF + Automatic Transition + JMAnimatedImageView cache"; cell.jmDetailsLabel.text = @"Swipe left / Right"; break; - case JMDemoGIFInteractiveAnimationUsingImageViewImageAndSystemCache: - cell.jmLabel.text = @"GIF INTERACTION : using JMAnimatedImageView (Low memory usage)"; + case 6: + cell.jmLabel.text = @"GIF + Interactive Transition + JMAnimatedImageView cache"; cell.jmDetailsLabel.text = @"Swipe left / Right"; break; default: break; } - - /* - cell.jmLabel.text = @"MULTIPLE GIF ANIMATIONS : using JMAnimatedImageView (Low memory usage)"; - cell.jmDetailsLabel.text = @""; - */ - return cell; } @@ -114,18 +103,50 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; - if (indexPath.row == JMDemoGIFAutomaticAnimationUsingImageViewImageAndSystemCache || - indexPath.row == JMDemoGIFInteractiveAnimationUsingImageViewImageAndSystemCache) - { + JMDemoType demoType = 0; + switch (indexPath.row) { + case 0: + demoType = ( JMDemoAutomatic | JMDemoMemoryBySystem | JMDemoChangeImageNoTransition); + break; + + case 1: + demoType = ( JMDemoAutomatic | JMDemoMemoryBySystem | JMDemoChangeImageNoTransition); + break; + + case 2: + demoType = ( JMDemoAutomatic | JMDemoMemoryByMyComponent | JMDemoChangeImageNoTransition); + break; + + case 3: + demoType = ( JMDemoInteractive | JMDemoMemoryByMyComponent | JMDemoChangeImageNoTransition | JMDemoReverseImage); + break; + + case 4: + demoType = ( JMDemoInteractive | JMDemoMemoryByMyComponent | JMDemoChangeImageSwipeTransition | JMDemoPhotos); + break; + + case 5: + demoType = ( JMDemoAutomatic | JMDemoMemoryByMyComponent | JMDemoChangeImageNoTransition); + break; + + case 6: + demoType = ( JMDemoInteractive | JMDemoMemoryByMyComponent | JMDemoChangeImageNoTransition); + break; + + default: + break; + } + + if (indexPath.row > 4) { JMFLViewController *vc = [JMFLViewController new]; UIViewController *vcToPush = vc; - vc.demoExemple = indexPath.row; + vc.demoExemple = demoType; [self.navigationController pushViewController:vcToPush animated:YES]; } else { JMViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"JMViewController"]; UIViewController *vcToPush = vc; - vc.demoExemple = indexPath.row; + vc.demoExemple = demoType; [self.navigationController pushViewController:vcToPush animated:YES]; } } diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMViewController.m b/JMAnimatedImageView/JMAnimatedImageView/JMViewController.m index 680db25..0bb416c 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMViewController.m +++ b/JMAnimatedImageView/JMAnimatedImageView/JMViewController.m @@ -24,6 +24,50 @@ - (void)viewDidLoad [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. + if (self.demoExemple & JMDemoAutomatic) { + if (self.demoExemple & JMDemoChangeImageSwipeTransition) { + self.carImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinear; + + } else { + self.carImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; + } + + } + + if (self.demoExemple & JMDemoInteractive) { + self.carImageView.animationType = JMAnimatedImageViewAnimationTypeInteractive; + + if (self.demoExemple & JMDemoChangeImageSwipeTransition) { + self.carImageView.animationType = JMAnimatedImageViewAnimationTypeManualSwipe; + } + } + + if (self.demoExemple & JMDemoMemoryBySystem) { + self.carImageView.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageSystemCache; + + } else { + self.carImageView.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; + + } + + if (self.demoExemple & JMDemoReverseImage) { + self.carImageView.imageOrder = JMAnimatedImageViewOrderReverse; + } + + self.imageView.hidden = YES; + self.carImageView.hidden = NO; + self.carImageView.animationDelegate = self; + self.carImageView.animationDatasource = self; + self.carImageView.animationRepeatCount = 0; + self.carImageView.animationDuration = 4.0; + + if (self.demoExemple & JMDemoAutomatic) { + [self.carImageView startAnimating]; + } else { + [self.carImageView setCurrentIndex:0 animated:NO]; + } + + /* switch (self.demoExemple) { case JMDemoAutomaticAnimationUsingImageViewImageAndSystemCache: { @@ -65,7 +109,7 @@ - (void)viewDidLoad self.carImageView.animationDatasource = self; self.carImageView.animationRepeatCount = 0; self.carImageView.animationDuration = 4.0; - self.carImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinear; + self.carImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; self.carImageView.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; self.carImageView.imageOrder = JMAnimatedImageViewOrderNormal; @@ -118,12 +162,13 @@ - (void)viewDidLoad [self.carImageView setInteractiveAnimation:YES]; break; - case JMDemoGIFAutomaticAnimationUsingImageViewImageAndSystemCache: + case JMDemoGIFAutomaticAnimationUsingImageViewImageAndLightMemory: self.imageView.hidden = YES; self.carImageView.hidden = NO; self.carImageView.animationDelegate = self; self.carImageView.animationDatasource = self; self.carImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; + self.carImageView.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; [self.carImageView reloadAnimationImagesFromGifNamed:@"rock"]; [self.carImageView startAnimating]; break; @@ -136,13 +181,14 @@ - (void)viewDidLoad default: break; } + */ } #pragma mark - JMOImageViewAnimationDatasource - (NSInteger)numberOfImagesForAnimatedImageView:(UIImageView *)imageView { - if (self.animationType == JMAnimatedImageViewAnimationTypeManualSwipe) { + if (self.demoExemple & JMDemoPhotos) { return 11; } return 70; @@ -150,7 +196,7 @@ - (NSInteger)numberOfImagesForAnimatedImageView:(UIImageView *)imageView - (NSString *)imageNameAtIndex:(NSInteger)index forAnimatedImageView:(UIImageView *)imageView { - if (self.animationType == JMAnimatedImageViewAnimationTypeManualSwipe) { + if (self.demoExemple & JMDemoPhotos) { return [NSString stringWithFormat:@"%d_verge_super_wide.jpg",(int)index]; } @@ -159,7 +205,7 @@ - (NSString *)imageNameAtIndex:(NSInteger)index forAnimatedImageView:(UIImageVie - (NSInteger)firstIndexForAnimatedImageView:(UIImageView *)imageView { - if (self.animationType == JMAnimatedImageViewAnimationTypeManualSwipe) { + if (self.demoExemple & JMDemoPhotos) { return 0; } From a9e064d047f9b30856503651695f72d51d94c66a Mon Sep 17 00:00:00 2001 From: Jerome Morissard Date: Thu, 14 May 2015 14:46:14 +0200 Subject: [PATCH 3/3] Update README --- .../JMAnimatedImageView-Info.plist | 4 +- README.md | 50 ++++++++++++------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView-Info.plist b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView-Info.plist index cf21731..72fe0b5 100644 --- a/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView-Info.plist +++ b/JMAnimatedImageView/JMAnimatedImageView/JMAnimatedImageView-Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.2.3 + 0.2.4 CFBundleSignature ???? CFBundleVersion - 0.2.3 + 0.2.4 LSRequiresIPhoneOS UIMainStoryboardFile diff --git a/README.md b/README.md index d8b2be8..30cd083 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ JMAnimatedImageView is a performant subclass of UIImageView: - Improve documentation - Fix retain cycle (Thanks Instruments!) -- JMGif allocation for a better integration with your favorites network libraries (initWithData:(NSData *)data fromURL:(NSURL *)url;) +- JMGif allocation for a better integration with your favorites network libraries. ## Installation @@ -28,11 +28,11 @@ $ pod try JMAnimatedImageView ``` ## Usage -### For a local animation from files into bundle +### For a local animation using file from a bundle In your code, `#import "JMAnimatedImageView.h"` and `#import "JMAnimatedImageView.h"` -```objective-c +``` //GIF example @property (weak, nonatomic) IBOutlet JMAnimatedImageView *jmImageView; @@ -41,7 +41,7 @@ self.jmImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinear [self.jmImageView startAnimating]; ``` -```objective-c +``` //PNG example with manual animation @property (weak, nonatomic) IBOutlet JMAnimatedImageView *jmImageView; @@ -50,6 +50,7 @@ self.jmImageView.animationDatasource = self; [self.jmImageView reloadAnimationImages]; // self.jmImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutAnimation; self.jmImageView.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; +[self.jmImageView startAnimating]; ``` ### For a remote Gif @@ -64,11 +65,31 @@ self.jmImageView.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowM [self.animatedImageView startAnimating]; }]; ``` +### For a remote Gif using AFNetworking + +```objective-c + NSURLRequest *req = [NSURLRequest requestWithURL:url]; + + AFHTTPRequestOperation *postOperation = [[AFHTTPRequestOperation alloc] initWithRequest:req]; + [postOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { + self.animatedImageView.animationType = JMAnimatedImageViewAnimationTypeAutomaticLinearWithoutTransition; + self.animatedImageView.memoryManagementOption = JMAnimatedImageViewMemoryLoadImageLowMemoryUsage; + [self.animatedImageView reloadAnimationImagesFromGifData:responseObject fromUrl:url]; + [self.animatedImageView startAnimating]; + + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + NSLog(@"Image error: %@", error); + block(NO, nil); + }]; + + [postOperation start]; +``` -Some parameters : +### Customizations * AnimationType -```objc + +```objective-c typedef NS_ENUM(NSUInteger, JMAnimatedImageViewAnimationType) { //Animation is done by a gesture JMAnimatedImageViewAnimationTypeInteractive = 0, @@ -84,24 +105,19 @@ typedef NS_ENUM(NSUInteger, JMAnimatedImageViewAnimationType) { ``` * MemoryOption -```objc + +```objective-c typedef NS_ENUM(NSUInteger, JMAnimatedImageViewMemoryOption) { - //images memory will be retain by system - JMAnimatedImageViewMemoryLoadImageSystemCache = 0, - - //image are loaded in live - JMAnimatedImageViewMemoryLoadImageLowMemoryUsage, - - //you load your images has you want - JMAnimatedImageViewMemoryLoadImageCustom + JMAnimatedImageViewMemoryLoadImageSystemCache = 0, //images memory will be retain by system + JMAnimatedImageViewMemoryLoadImageLowMemoryUsage, //images loaded but not retained by the system + JMAnimatedImageViewMemoryLoadImageCustom //images loaded by you (JMOImageViewAnimationDatasource) }; ``` * ImageViewOrder -```objc +```objective-c typedef NS_ENUM(NSUInteger, JMAnimatedImageViewOrder) { - JMAnimatedImageViewOrderNone = 0, JMAnimatedImageViewOrderNormal = 1, JMAnimatedImageViewOrderReverse = -1 };