我正在尝试创建一个Animations Manager类,它将为我处理递归动画。它工作正常,但不可靠。例如,有时候,使用它时,动画会发生并且背靠背"因为它们之间没有延迟。其他时候使用它时,动画之间会有延迟(这种情况发生在其他视图控制器上的其他元素上)
这是我的代码:
@implementation customAnimationTimer
-(id) initWithTimeInterval:(NSTimeInterval)timeInterval target:(UIView*)target animationType:(NSInteger)animationType
fromValue:(CGFloat)fromValue toValue:(CGFloat)toValue withDelegate:(id <customAnimationTimerDelegate>)delegate {
if (self = [super init]) {
self.delegate = delegate;
_timeInterval = timeInterval;
_target = target;
_animationState = NO;
_animationType = animationType;
_fromValue = fromValue;
_toValue = toValue;
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkFire)];
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
return self;
}
-(void) displayLinkFire {if (self.delegate) [self.delegate displayLinkUpdate:self];}
@end
@implementation animationManager
static animationManager* sharedHelper = nil;
+ (animationManager*) sharedInstance {
if (!sharedHelper) sharedHelper = [[animationManager alloc] init];
return sharedHelper;
}
-(id) init { if (self = [super init]) {[self initArrays];} return self;}
-(void) initArrays {
_activeTimers = [NSMutableArray arrayWithObjects: nil];
}
-(void) displayLinkUpdate:(customAnimationTimer*)timer {
if (timer.displayLink.frameInterval != 1) [self animateWithTimer:timer];
timer.displayLink.frameInterval = (timer.timeInterval/timer.displayLink.duration);
}
-(void) animateWithTimer:(customAnimationTimer*)timer {
if (!timer.animationState) {
timer.animationState = true;
[UIView animateWithDuration:timer.timeInterval animations:^{
if (timer.animationType == 0) timer.target.alpha = timer.toValue;
}];
} else {
timer.animationState = false;
[UIView animateWithDuration:timer.timeInterval animations:^{
if (timer.animationType == 0) timer.target.alpha = timer.fromValue;
}];
}
}
-(void) addAnimationToView:(UIView*)view withType:(int)animationType fromValue:(CGFloat)fromValue toValue:(CGFloat)toValue withTime:(CGFloat)time {
[_activeTimers addObject: [[customAnimationTimer alloc] initWithTimeInterval:time target:view animationType:animationType fromValue:fromValue toValue:toValue withDelegate:self]];
}
-(void) removeAnimationFromView:(UIView*)view {
NSInteger index = 900000000;
for (customAnimationTimer* timer in _activeTimers) {
if (timer.target == view) {
index = [_activeTimers indexOfObject:timer];
[timer.displayLink invalidate];
}
}
if (index != 900000000) [_activeTimers removeObjectAtIndex:index];
}
-(void) removeAnimations {
for (customAnimationTimer* timer in _activeTimers) [timer.displayLink invalidate];
[self initArrays];
}
@end
答案 0 :(得分:0)
您可能正在模拟器中进行测试。唐&#39;吨。 CADisplayLink在模拟器中完全不可靠。如果您要使用CADisplayLink,请仅在设备上进行测试。
您的代码的另一个问题是您永远不应该假设CADisplayLink会触发的频率。它不会定期开火。始终查看timestamp
以了解实际实施的时间,并计算动画&#34;框架&#34;基于此。
在我自己的代码的这个例子中,我调用了第一个&#34; frame&#34;动画0
和最后一帧&#34;帧&#34;整个动画1
。因此我可以计算出正确的#34;框架#34;通过比较时间戳和总持续时间来动画。我在一些实例变量中维护状态。以下是显示链接触发时发生的情况:
if (self->_timestamp < 0.01) { // pick up and store first timestamp
self->_timestamp = sender.timestamp;
self->_frame = 0.0;
} else { // calculate frame
self->_frame = (sender.timestamp - self->_timestamp) * SCALE;
}
// ... redraw here ...
if (self->_frame > 1.0) {
[sender invalidate];
self->_frame = 0.0;
self->_timestamp = 0.0;
}
答案 1 :(得分:0)
好吧,录制完并播放了两张唱片,我的眼睛确实是我的伎俩!其中一个是蓝色背景,另一个是红色背景,我想这与它有关!我向那些我困惑的人道歉!