Created
March 11, 2011 17:44
-
-
Save hartbit/866250 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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