CADisplayLink失效后无法停止
CADisplayLink can't stop after invalidated
我有两个 UIButton
,第一个按钮将触发 CustomeView 的 - beginAnimation
,另一个将触发 - endAnimation
。当我依次快速按下这两个按钮时,如begin -> end -> begin -> end -> begin -> end
,我发现CADisplayLink
根本停不下来。更何况- rotate
的射速已经超过60fps,变成了60 -> 120 -> 180
,就像我的主RunLoop里多了一个CADisplaylink
一样,请问有什么方法可以解决吗?而且我需要在视图的alpha变为零之前保持CADisplaylink
运行,所以我将[self.displayLink invalidate];
放在完成块中,也许这会导致这个问题?
@interface CustomeView : UIView
@end
@implementation CustomeView
- (void)beginAnimation // triggered by a UIButton
{
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 1.0; }];
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotate)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)endAnimation // triggered by another UIButton
{
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 0.0; } completion:^(BOOL finished) {
[self.displayLink invalidate];
}];
}
- (void)rotate
{
// ....
}
如果您在 -endAnimation
中的完成块有 运行 之前调用 -beginAnimation
-- 也就是说,在 0.5 秒动画完成之前 -- 您将覆盖旧的 self.displayLink
用新的。之后,当完成块 运行s 时,您将使新显示 link 无效,而不是旧显示。
使用中间变量捕获 self.displayLink
的值,该值保存要使显示 link 无效的值。此外,为了更好地衡量,在完成后将 self.displayLink
设置为 nil。
- (void)beginAnimation // triggered by a UIButton
{
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 1.0; }];
if (self.displayLink != nil) {
// You called -beginAnimation before you called -endAnimation.
// I'm not sure if your code is doing this or not, but if it does,
// you need to decide how to handle it.
} else {
// Make a new display link.
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotate)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
}
- (void)endAnimation // triggered by another UIButton
{
if (self.displayLink == nil) {
// You called -endAnimation before -beginAnimation.
// Again, you need to determine what, if anything,
// to do in this case.
} else {
CADisplayLink oldDisplayLink = self.displayLink;
self.displayLink = nil;
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 0.0; } completion:^(BOOL finished) {
[oldDisplayLink invalidate];
}];
}
}
我有两个 UIButton
,第一个按钮将触发 CustomeView 的 - beginAnimation
,另一个将触发 - endAnimation
。当我依次快速按下这两个按钮时,如begin -> end -> begin -> end -> begin -> end
,我发现CADisplayLink
根本停不下来。更何况- rotate
的射速已经超过60fps,变成了60 -> 120 -> 180
,就像我的主RunLoop里多了一个CADisplaylink
一样,请问有什么方法可以解决吗?而且我需要在视图的alpha变为零之前保持CADisplaylink
运行,所以我将[self.displayLink invalidate];
放在完成块中,也许这会导致这个问题?
@interface CustomeView : UIView
@end
@implementation CustomeView
- (void)beginAnimation // triggered by a UIButton
{
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 1.0; }];
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotate)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)endAnimation // triggered by another UIButton
{
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 0.0; } completion:^(BOOL finished) {
[self.displayLink invalidate];
}];
}
- (void)rotate
{
// ....
}
如果您在 -endAnimation
中的完成块有 运行 之前调用 -beginAnimation
-- 也就是说,在 0.5 秒动画完成之前 -- 您将覆盖旧的 self.displayLink
用新的。之后,当完成块 运行s 时,您将使新显示 link 无效,而不是旧显示。
使用中间变量捕获 self.displayLink
的值,该值保存要使显示 link 无效的值。此外,为了更好地衡量,在完成后将 self.displayLink
设置为 nil。
- (void)beginAnimation // triggered by a UIButton
{
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 1.0; }];
if (self.displayLink != nil) {
// You called -beginAnimation before you called -endAnimation.
// I'm not sure if your code is doing this or not, but if it does,
// you need to decide how to handle it.
} else {
// Make a new display link.
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotate)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
}
- (void)endAnimation // triggered by another UIButton
{
if (self.displayLink == nil) {
// You called -endAnimation before -beginAnimation.
// Again, you need to determine what, if anything,
// to do in this case.
} else {
CADisplayLink oldDisplayLink = self.displayLink;
self.displayLink = nil;
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 0.0; } completion:^(BOOL finished) {
[oldDisplayLink invalidate];
}];
}
}