【发布时间】:2014-04-02 13:01:43
【问题描述】:
我正在尝试创建一个动画管理器类,它将为我处理递归动画。它正在工作,但不可靠。例如,有时,当使用它时,动画会“背靠背”发生,它们之间没有延迟。其他时候使用它时,动画之间会留下延迟(这发生在位于其他视图控制器上的其他元素上)
这是我的代码:
@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
【问题讨论】:
-
在所有专门用于同步绘图和计时的对象中,您必须选择与绘图无关的对象。维护一个回调池,而不是计时器。 NSTimer 不够可靠,无法用于接近动画计时的任何事情。
-
恐怕仍然得到相同的结果。它似乎在正确的时间调用所有内容,但动画并没有在正确的时间发生。我已经用新代码更新了 OP。对出了什么问题有任何想法吗?
-
是否在主线程上调用了 CADisplayLink 回调?另外,我注意到您正在使用 [UIView animateWithDuration] 制作动画。这最终将安排在 runLoop 上。我不认为你可以保证动画会立即运行(至少不能以帧精确精度)。
-
是的,它发生在主线程上。也不是延迟几帧的情况。。我这里说的是半秒!
标签: iphone objective-c uiview cadisplaylink