Iphone 如何正确停止和恢复CADisplayLink?

Iphone 如何正确停止和恢复CADisplayLink?,iphone,ios,performance,cadisplaylink,Iphone,Ios,Performance,Cadisplaylink,我发现了CADisplayLink的一个大问题 我用OpenGLES1.1绘制了一个旋转的三角形来进行测试,这是最基本的Eaglelayer。这需要以屏幕刷新率调用run loop方法,因此我按如下方式启动runloop: - (void)startRunloop { if (!animating) { CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selec

我发现了CADisplayLink的一个大问题

我用OpenGLES1.1绘制了一个旋转的三角形来进行测试,这是最基本的Eaglelayer。这需要以屏幕刷新率调用run loop方法,因此我按如下方式启动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;
    }
}
当测试应用程序启动时,我调用-startRunloop。 当我点击屏幕时,我调用-stopRunloop。 当我再次点击时,我调用-startRunloop。等等乒乓球

我正在测量-drawFrame方法在20秒内被调用的频率,并记录它

  • 第一次启动/停止循环始终以100%执行。我得到了最大帧速率

  • 所有后续启动/停止循环仅显示约80%的性能。我得到的帧速率要小得多。但是:总是几乎完全相同,+/-2帧。即使在50次以上的启动/停止循环后,也没有进一步降级的趋势

总之:像我上面所做的那样创建一个Cadisplay链接是可以的,直到它失效或暂停。在此之后,任何新的CADisplayLink都不再表现良好。即使它是以与以前完全相同的方式创建的。如果我使用YES/NO调用-setPaused:方法暂停/恢复它,情况也是如此

我已经通过分配和VM跟踪工具确保没有内存管理问题。我还检查了CADisplayLink的-invalidate方法是否真的被调用

设备上的iOS 4.0(iPhone 4)


为什么呢?我遗漏了什么吗?

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

另外,您也可以暂停显示链接。

我正在使用

[displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
 - (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;
}

看看它是否适合您

我想您真正想要的是暂停并取消显示链接

 - (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;
}
用斯威夫特试试这个

displayLink?.remove(from: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)

适用于Swift 4.2

displayLink.remove(from: RunLoop.current, forMode: RunLoop.Mode.common)

听起来像个虫子。我想你需要向苹果公司提交一份缺陷报告。我也有同样的问题。我不需要DisplayLink一直运行,但看起来我没有选择。所以现在我只是在处理程序选择器中使用标志,而不是使用isPaused。