尝试将dispatch_async与cocos2d函数一起使用时出错

时间:2014-01-03 01:44:16

标签: ios iphone cocos2d-iphone grand-central-dispatch

我正在构建一个滚动菜单,可以动态生成新的按钮行,并且必须从大量精灵中生成每个按钮。因为这是处理器密集型的,所以每次需要加载新的按钮行时,菜单会粘住大约四分之一秒。我意识到我需要添加多线程,因此按钮加载可以在与滚动动画不同的线程中处理,但是当我这样做时它会在尝试加载新按钮时崩溃。这是我正在使用的代码:

-(void)addRowBelow{
    _rowIndex--;
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSMutableArray *row = [self addRow:_rowIndex];
        [_buttonGrid addObject:row];
        [self removeRow:[_buttonGrid objectAtIndex:0]];
    });
    _nextRowBelowPos += _rowHeight;
    _nextRowAbovePos += _rowHeight;
}

每次测试时我都会遇到不同的错误,有时会出现内存错误或断言失败。我怀疑它与异步调用cocos2d函数有关吗?

2 个答案:

答案 0 :(得分:2)

您可能会遇到崩溃问题,因为您对cocos托管对象(精灵,图层,节点等)进行多线程访问。由于引擎希望使用这些对象的内部进行显示,GPU操作等,并且 NOT 线程安全,因此您可能无法获得多线程的良好结果。 您可能正在使用它时正在更改内容

动态创建/销毁精灵可能是你减速的原因。 Cocos2d可以以60 fps的速度在屏幕上显示很多(我认为它大约是2k)对象......只要你不做任何创建/破坏或AI就可以减少它。

我建议您在场景进入舞台之前预先加载所有精灵。您可以在前景场景或场景本身的初始化中执行此操作,并让场景拥有精灵。然后你可以在update()调用期间迭代它们并改变它们的位置,使可见/不可见等等。

作为参考,我通常会创建不同的“精灵图层”,除了场景之外还会加载所有精灵。如果我要使用动态对象,我会尝试预先分配一些并在可能的情况下回收它们。这也允许我控制屏幕上“什么在屏幕前面”的顺序(see example here)。每一层还绘制了特定“实体类型”的元素,为许多显示提供了一个漂亮的“MVC”字符。

这类似于iPhone Apps回收表格单元格的方式。

只有在您第一次需要它们时才创建它们,并且在您需要它们之前就有一个藏匿处。

这有用吗?

答案 1 :(得分:0)

您可能想要使用的模式是

  1. 将工作分派给后台线程。 (请注意,在后台线程上执行工作必须是安全的。)
  2. 发回主线程以更新您的用户界面。
  3. 以下是代码中的示例:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
        // Do work that is safe to execute in the background.
        // For example, reading images from disk.
    
        dispatch_async(dispatch_get_main_queue(), ^{
    
            // Do work here that must execute on the main thread.
            // For example, calling Cocos2D objects' methods.
    
            NSMutableArray *row = [self addRow:_rowIndex];
            [_buttonGrid addObject:row];
            [self removeRow:[_buttonGrid objectAtIndex:0]];
    
        });
    });