Skip to content

Instantly share code, notes, and snippets.

@hartbit
Created March 11, 2011 17:44
Show Gist options
  • Save hartbit/866250 to your computer and use it in GitHub Desktop.
Save hartbit/866250 to your computer and use it in GitHub Desktop.
//
// HDAnimatedImage.m
// HDFoundation
//
// Created by David Hart on 11/9/10.
// Copyright 2010 hart[dev]. All rights reserved.
//
#import "HDAnimatedImage.h"
#import <QuartzCore/QuartzCore.h>
#import "UIImage+Loading.h"
@interface HDAnimatedImage ()
@property (nonatomic, assign) CADisplayLink* displayLink;
@property (nonatomic, assign) NSUInteger currentFrame;
@property (nonatomic, retain) NSArray* images;
- (void)initialize;
- (UIImage*)imageWithIndex:(NSUInteger)index;
- (void)createImages;
- (void)createDisplayLink;
- (void)updateAnimation:(CADisplayLink*)sender;
@end
@implementation HDAnimatedImage
@synthesize animationName = _animationName;
@synthesize animationFrequency = _animationFrequency;
@synthesize stopsOnLastFrame = _stopsOnLastFrame;
@synthesize delegate = _delegate;
@synthesize displayLink = _displayLink;
@synthesize currentFrame =_currentFrame;
@synthesize images = _images;
#pragma mark - Initialization
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (!self) return nil;
[self initialize];
return self;
}
- (id)initWithCoder:(NSCoder*)coder
{
self = [super initWithCoder:coder];
if (!self) return nil;
[self initialize];
return self;
}
- (id)initWithImage:(UIImage*)image
{
self = [super initWithImage:image];
if (!self) return nil;
[self initialize];
return self;
}
- (void)initialize
{
[self setAnimationFrequency:12];
}
#pragma mark - Properties
- (void)setAnimationName:(NSString*)animationName
{
if ([animationName isEqualToString:_animationName]) return;
[_animationName release];
if (animationName == nil) return;
_animationName = [animationName copy];
[self setImage:[self imageWithIndex:0]];
}
- (void)setAnimationDuration:(NSTimeInterval)animationDuration
{
[super setAnimationDuration:animationDuration];
NSArray* images = [self images];
if (images)
{
_animationFrequency = [images count] / animationDuration;
}
}
- (void)setAnimationFrequency:(NSUInteger)animationFrequency
{
_animationFrequency = animationFrequency;
NSArray* images = [self images];
if (images)
{
NSTimeInterval animationDuration = [images count] / (NSTimeInterval)animationFrequency;
[super setAnimationDuration:animationDuration];
}
}
- (void)setAnimationImages:(NSArray*)animationImages
{
}
#pragma mark - UIImageView Methods
- (void)startAnimating
{
if ([self isAnimating]) return;
[self setCurrentFrame:0];
[self createImages];
[self createDisplayLink];
}
- (void)stopAnimating
{
if (![self isAnimating]) return;
[_displayLink invalidate];
[self setDisplayLink:nil];
[self setImages:nil];
if ([_delegate respondsToSelector:@selector(animatedImageDidFinishAnimating:)])
{
[_delegate animatedImageDidFinishAnimating:self];
}
}
- (BOOL)isAnimating
{
return _displayLink != nil;
}
#pragma mark - Private Methods
- (UIImage*)imageWithIndex:(NSUInteger)index
{
NSAssert(_animationName, @"No animationName provided.");
NSString* imageName = [_animationName stringByAppendingFormat:@"%i", index];
return [UIImage imageNamed:imageName cached:NO];
}
- (void)createImages
{
NSAssert(!_images, @"Images should not hanging aorund by now.");
NSMutableArray* images = [[NSMutableArray alloc] init];
NSUInteger index = 0;
UIImage* image = [self imageWithIndex:index];
while (image != nil)
{
[images addObject:image];
index++;
image = [self imageWithIndex:index];
}
[self setImages:images];
if ([self animationDuration] == 0)
{
[self setAnimationFrequency:_animationFrequency];
}
else
{
[self setAnimationDuration:[self animationDuration]];
}
[images release];
}
- (void)createDisplayLink
{
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateAnimation:)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[self setDisplayLink:displayLink];
}
- (void)updateAnimation:(CADisplayLink*)sender
{
NSArray* images = [self images];
// Update Frame Interval
NSTimeInterval animationPeriod = [self animationDuration] / [images count];
[_displayLink setFrameInterval:(NSInteger)(animationPeriod / [_displayLink duration])];
if (_currentFrame == [images count])
{
NSInteger animationRepeatCount = [self animationRepeatCount];
if (animationRepeatCount == 1)
{
[self stopAnimating];
return;
}
else
{
if (animationRepeatCount > 1)
{
[self setAnimationRepeatCount:animationRepeatCount - 1];
}
_currentFrame = 0;
}
}
UIImage* image = [images objectAtIndex:_currentFrame];
[self setImage:image];
[self setNeedsDisplay];
NSLog(@"[%p setImage:%p]", self, image);
_currentFrame++;
}
#pragma mark - Memory Management
- (void)dealloc
{
[self stopAnimating];
[self setAnimationName:nil];
[self setImages:nil];
[super dealloc];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment