如何正确停止和恢复CADisplayLink?

don*_*ile 13 iphone performance ios cadisplaylink

我发现了CADisplayLink的一个大问题.

我有最基本的EAGLLayer与OpenGL ES 1.1绘制旋转三角形进行测试.这需要以屏幕刷新率调用运行循环方法,所以我像这样启动runloop:

- (void)startRunloop {
    if (!animating) {
        CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(drawFrame)];
        [dl setFrameInterval:1.0];
        [dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        self.displayLink = dl;

        animating = YES;
    }
}

- (void)stopRunloop {
    if (animating) {
        [self.displayLink invalidate];
        self.displayLink = nil;
        animating = NO;
    }
}
Run Code Online (Sandbox Code Playgroud)

当测试应用程序启动时,我调用-startRunloop.当我点击屏幕时,我调用-stopRunloop.当我再次点击时,我调用-startRunloop.等等.乒乓.

我正在测量在20秒内调用-drawFrame方法的频率,以及NSLog它.

  • FIRST启动/停止循环始终执行100%.我得到了最大帧速率.

  • 所有SUBSEQUENT启动/停止循环仅显示约80%的性能.我的帧速率要小得多.但是:总是几乎完全相同,+/ - 2帧.即使经过50次启动/停止循环后也没有进一步降级的倾向.

总结:像我上面那样创建CADisplayLink是好的,直到它失效或暂停.之后,任何新的CADisplayLink都不再表现良好.即使它是以与以前完全相同的方式创建的.如果我通过使用YES/NO调用-setPaused:方法暂停/恢复它也是如此.

我已经确定Allocations和VM Tracker Instruments没有内存管理问题.我还检查过CADisplayLink的-invalidate方法是否真的被调用了.

设备上的iOS 4.0(iPhone 4).

这是为什么?我错过了什么吗?

小智 9

我认为你真正想要的只是暂停和取消暂停你的显示链接.

 - (void)createRunloop {
    CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(drawFrame)];
    [dl setFrameInterval:1.0];
    [dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    self.displayLink = dl;
    // start in running state, your choice.
    dl.paused = NO;
}
- (void)startRunloop {
    self.displayLink.paused = NO;
}
- (void)stopRunloop {
    self.displayLink.paused = YES;
}
- (void)destroyRunloop {
        [self.displayLink invalidate];
        self.displayLink = nil;
}
Run Code Online (Sandbox Code Playgroud)


Kun*_*jar 5

我在用

[displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
Run Code Online (Sandbox Code Playgroud)

看看它是否适合你


Har*_*kar 5

对于斯威夫特 4.2

displayLink.remove(from: RunLoop.current, forMode: RunLoop.Mode.common)
Run Code Online (Sandbox Code Playgroud)


Luc*_*cas 2

您可以在每次启动调用时创建一个新的显示链接实例。您是否尝试过重复使用同一个实例?

此外,您始终可以暂停显示链接。