gpt4 book ai didi

ios - CADisplayLink 目标选择器在失效后被触发

转载 作者:技术小花猫 更新时间:2023-10-29 11:22:14 26 4
gpt4 key购买 nike

我有一个 CADisplayLink 触发 Director 对象中的 draw 方法。我想使 CADisplayLink 无效,然后解除分配一些由 Director 对象使用的单例缓存对象。 draw 方法不保留单例缓存对象。

在 Director 中一个名为 stopAnimation 的方法中(此方法与 draw 方法无关),我这样做:

[displayLink invalidate];

然后我开始释放单例缓存对象,但随后 CADisplayLink 触发并且最后一次调用了 draw 方法。 draw 方法尝试访问已释放的单例对象,但一切都崩溃了。

这只是有时会发生:有时应用程序不会崩溃,因为缓存对象在 displayLink 实际上无效并且 draw 方法已经完成运行后被释放。

在使 displayLink 无效后,我如何检查 draw 方法是否已完成运行并且不会再次触发,以便安全地使 Cache 对象无效?如果可能,我不想修改 draw 方法。

我尝试了多种组合,包括在主线程上执行displayLink invalidate

[self performSelectorOnMainThread:@selector(stopAnimation) withObject:self waitUntilDone:YES]

或尝试在当前运行循环中使用

[[NSRunLoop currentRunLoop] performSelector:@selector(stopAnimation) target:self 参数:nil order:10 modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];

但结果总是一样的,有时过早释放共享缓存。

我也不想使用具有任意延迟的 performSelector:withObject:afterDelay: 方法。我想确保 displayLink 无效,draw 方法结束,并且不会再次运行。

最佳答案

这可能有点晚了,但是因为没有答案......

我不认为,你的选择器被再次调用,而是显示链接的线程在你的绘制框架方法的中间。在任何情况下,问题都是一样的。这是多线程,尝试在一个线程中释放一些对象而在另一个线程中使用它们通常会导致冲突。

可能最简单的解决方案是在绘制框架方法中放置一个标志和一个“if 语句”作为

if(schaduledForDestruction) {
[self destroy];
return;
}

然后在任何使显示链接无效的地方将“schaduledForDestruction”设置为 YES。

如果您真的认为显示链接会再次调用此方法,您可以在那个“destructionInProgress”中使用另一个 if。

如果你不想改变绘制框架的方法,你可以尝试将一个新的选择器强制到显示链接...

CADisplayLink *myDisplayLink;
BOOL resourcesLoaded;
SEL drawSelector;

- (void)destroy {
if(resourcesLoaded) {
[myDisplayLink invalidate];
//free resources
resourcesLoaded = NO;
}
}
- (void)metaLevelDraw {
[self performSelector:drawSelector];
}
- (void)drawFrame {
//draw stuff
}
- (void)beginAnimationing {
drawSelector = @selector(drawFrame);
myDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(metaLevelDraw)];
[myDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)endAnimationing {
drawSelector = @selector(destroy);
}

或者只是考虑这样的事情(但我不能说这是安全的。如果新创建的显示链接可以在与原始线程不同的线程上运行选择器,那么它什么也解决不了)。

CADisplayLink *myDisplayLink;
BOOL resourcesLoaded;

- (void)destroy {
if(resourcesLoaded) {
[myDisplayLink invalidate];
//free resources
resourcesLoaded = NO;
}
}
- (void)drawFrame {
//draw stuff
}
- (void)beginAnimationing {
myDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawFrame)];
[myDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)endAnimationing {
[myDisplayLink invalidate];
myDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(destroy)];
[myDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

关于ios - CADisplayLink 目标选择器在失效后被触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6418876/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com