UIMAGEVIEW has an AnimationImages property to play animation to imitate the attribute of UIImageView, and use CadisplayLink to play frame animation.
1. Introduction (original address: http://www.tuicool.com/articleS/memvr3))
1, the framework
The
CadisplayLink is the same as other Coreanimation classes, all in Quartzcore.framework.
2, function
CadisplayLink’s main feature is that it can provide a periodic call for the Selector that we give it to it. From this point of view, it is similar to the timer Nstimer.
3. How to use
After
- (void)startDisplayLink
{
self.displayLink = [CADisplayLink displayLinkWithTarget:self
selector:@selector(handleDisplayLink:)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
}
- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
//do something
}
- (void)stopDisplayLink
{
[self.displayLink invalidate];
self.displayLink = nil;
}
When the CadisplayLink object adds it into Runloop, the selector can be called periodically, similar to the startup of Nstimer; when performing the Involution operation, the CadisplayLink object will be removed from the RunLoop. SELECTOR calls stop, similar to it, similar to Nstimer’s INVALIDATE method.
2, Features
The following combined with nstimer to introduce CadisplayLink. It is different from Nstimer:
1. Different principles
CadisplayLink is a timer class that allows us to draw a specific content on the screen at a frequency that allows us to synchronize with the screen refresh rate. After CADISPLAYLINK is registered with a specific mode to Runloop, when the screen display content is completed, Runloop will send a specified selector message to the target specified by CadisplayLink, and the selector corresponding to the CadisplayLink class will be called once.
Nstimer registered with Runloop in the specified mode. After the setting period is reached, Runloop sends a specified selector message to the specified target.
2, different cycle settings different ways
The screen refreshing frequency (FPS) of the
iOS device is 60Hz, so CadisplayLink’s selector’s default call cycle is 60 times per second. This cycle can be set through the frameinterval attribute. For example, when Frameinterval is set to 2, calls are called 30 times per second. Therefore, the setting of the CadisplayLink cycle is slightly inconvenient.
nstimer’s selector call cycle can be set directly when initialization, which is relatively flexible.
3. Different accuracy
The screen refreshing frequency of
iOS device is fixed. CadisplayLink will be called at each refresh, and the accuracy is quite high.
The accuracy of the
Nstimer is a bit lower. For example, when the trigger time of Nstimer is over, if the Runloop is busy with other calls, the trigger time will be postponed to the next Runloop cycle. What’s more, after OS X V10.9, in order to avoid triggering the time to the NSTimer to interrupt the current processing task, Nstimer adds the TOLARANCE attribute, allowing users to set the time range that can tolerate triggers.
4. Use occasions
In principle, it is not difficult to see that the use of CadisplayLink is relatively dedicated, suitable for constant re -painting for interfaces. For example, when video playback, you need to constantly obtain the next frame for interface rendering.
Nstimer’s use range is much widespread, and all kinds of tasks that require single or loop regular processing can be used.
3, important attributes
The incompletely listed several important attributes of CadisplayLink:
1、 frameInterval
Reading and write -able NSINTEGER type value, the identifier interval how many frames are called once the selector method, the default value is 1, that is, call once every frame. The official document emphasizes that when the value is set less than 1, the result is unpredictable.
2、duration
Read the CFTIMEINTERVAL value, indicating the time interval between the two screen refresh. It should be noted that this attribute will be assigned only after being called for the first time. SELECTOR call interval time calculation method is: time = duration × frameintervalval.
The FPS of the existing iOS device screen is 60Hz, which can be seen from the Duration property of CadisplayLink. The values of Duration are 0.1666666, that is, 1/60. Nevertheless, we can’t sure that Apple will not change the FPS. What if the FPS will be raised to 120Hz one day in the future? At this time, you set up the FrameInterval attribute value of 2 and expect to refresh 30 times per second, but find that it has been refreshed 60 times per second. As a result, you can imagine that, out of security considerations, first judge the screen of the screen based on the Duration. Essence
3、timestamp
Print the TimestAmp value, its style is similar to:
Although the
179699.631584
CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil];
NSLog("localLayerTime:%f",localLayerTime);
Four, pay attention
1. The degree of leisure of CPU
If the CPU is busy with other calculations, it will not guarantee that the 60Hz execution of the screen drawing action will cause the opportunity to skip several callback methods, and the number of times is determined to be the busyness of the CPU.
2. The time used to execute the callback method
If the delation time is greater than the interval between the redemption, it will cause a number of chance of callback calls, depending on the length of the execution time.
//
// AnimationImageView.h
// UseCADisplayLinkPlay animation
//
// Created by dengyanzhou on 15/1/30.
// Copyright (c) 2015year mobby. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef void (^AnimationComplete) (BOOL isFinished);
@interface AnimationImageView : UIImageView
@property(nonatomic)int step;
@property(nonatomic,strong)NSArray *animationImageArray;//The picture frame number array to be played
@property(nonatomic,copy)AnimationComplete tempAnimationComplete;
@property(nonatomic,assign)int index; //Positioning the picture currently played
@property(nonatomic)float animationTime; // Animation duration
@property(nonatomic)int count;
@property(nonatomic )float frequency; // frequency
@property(nonatomic) int transformatRate; //conversion rate
@property(nonatomic,strong)CADisplayLink*Displaylink; // timer
– (void)playAnimationWithImageArray:(NSArray*)animationArray durationTime:(float)time complete:(AnimationComplete)animationComplete;
@end
// Implementation file
//
// AnimationImageView.m
// UseCADisplayLinkPlay animation
//
// Created by dengyanzhou on 15/1/30.
// Copyright (c) 2015year mobby. All rights reserved.
//
#import “AnimationImageView.h”
#import “UIImageAdditions.h”
@implementation AnimationImageView
– (void)playAnimationWithImageArray:(NSArray*)animationArray durationTime:(float)time complete:(AnimationComplete)animationComplete{
// Animation playback array is empty Return directly The animation is not completed;
if (!animationArray.count ) {
animationComplete(NO);
return;
}
//Time is zero Return directly
if (time <= 0) {
return;
}
self.frequency = time/animationArray.count;
self.transformatRate = (int)(self.frequency * 60);
if (self.transformatRate == 0) {
self.transformatRate = 1;
}
//_disPlayelink There are still indicating that the animation is not completed
if (self.displayLink) {
//Make the animation stop
[_displayLink invalidate];
_displayLink = nil;
//count Return again 0
_count = 0;
_index = 0;
animationComplete(NO);
return;
}
self.animationImageArray = animationArray;
self.animationTime = time;
_count = 0;
_index = 0;
// timer
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateImage:)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop]forMode:NSDefaultRunLoopMode];
_tempAnimationComplete = animationComplete;
}
– (void)updateImage:(CADisplayLink*)displayLink{
//1s/60
if (++_count % self.transformatRate == 0 ) {
self.image = [UIImage getPNGImage: [_animationImageArray objectAtIndex:_index]];
//Animation complete
if (_index == self.animationImageArray.count – 1) {
[_displayLink invalidate];
_displayLink = nil;
self.animationImageArray = nil;
// Animation is completed block
self.tempAnimationComplete(YES);
}
_index++;
}
}
@end
// In case of institutionalization in viewControAnimationImageView and call
AnimationImageView object
– (void)playAnimationWithImageArray:(NSArray*)animationArray durationTime:(float)time complete:(AnimationComplete) AnimationComplete method
//
// ViewController.h
// UseCADisplayLinkPlay animation
//
// Created by dengyanzhou on 15/1/30.
// Copyright (c) 2015year mobby. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
//
// ViewController.m
// UseCADisplayLinkPlay animation
//
// Created by dengyanzhou on 15/1/30.
// Copyright (c) 2015year mobby. All rights reserved.
//
#import “ViewController.h”
#import “AnimationImageView.h”
@interface ViewController (){
NSMutableArray *imageArray;
AnimationImageView *imageView;
}
@end
@implementation ViewController
– (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
imageView = [[AnimationImageView alloc]initWithFrame:CGRectMake(100, 200, 320, 300)];
[self.view addSubview:imageView];
imageView.backgroundColor = [UIColor redColor];
imageArray = [NSMutableArray array];
for (int i = 1; i <= 68; i++) {
// NSString *imageName = @”7-8_Game2_bulusi 300″;
NSString *imageName = [NSString stringWithFormat:@”7-8_Game2_bulusi 300%02d”,i];
// UIImage *image = [UIImage imageNamed:imageName];
[imageArray addObject:imageName];
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(700, 400, 200, 80);
button.backgroundColor = [UIColor blueColor];
[button setTitle:@”Click to play“ forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
#if !__has_feature(objc_arc) // If notarc
[imageArray relese];
#endif
// Do any additional setup after loading the view, typically from a nib.
}
– (void)buttonClick{
// imageView.animationImages = [NSArray arrayWithArray:imageArray];
// imageView.animationRepeatCount = 1;
// imageView.animationDuration = 4.0f;
// [imageView startAnimating] ;
[imageView playAnimationWithImageArray: imageArray durationTime:3 complete:^(BOOL isFinished) {
if (isFinished) {
NSLog(@”Animation complete“);
}else{
NSLog(@”The animation is not completed“);
}
}];
}
– (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end