cocos2d не может добавить дочерний элемент асинхронно

Мне нужно получить некоторые данные из базы данных для отображения на экране. Я хочу избежать блокировки приложения, поэтому я показываю следующий экран, прежде чем извлекать какие-либо данные и добавлять данные по мере их поступления.

Это метод, который добавляет нужную мне информацию на экран:

- (void)initInfo
{
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    CCMenu *infoMenu;

    // get the info in seperate thread since it may block
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        infoMenu = [PlayerInfoHelper generateInfoForPlayerWithId:[PlayerManager sharedInstance].activePlayer.objectId tag:-1 sender:self];

        dispatch_async(dispatch_get_main_queue(), ^{
            if (infoMenu != nil) {
                infoMenu.position = ccp(winSize.width - kSSInfoPaddingX, winSize.height - kSSInfoPaddingY);
                [self addChild:infoMenu z:zIndex++]; // (1)
            }
        });
    });
}

Метод generateInfoForPlayerWithId:tag:sender: может блокироваться, поэтому я поместил его в отдельный поток. Я добавляю меню в основной поток, так как это UI-обновление.

Я уверен, что infoMenu является правильным объектом CCMenu*.

Я получаю EXC_BAD_ACCESS, когда не комментирую строку, обозначенную // (1).


person mmvie    schedule 03.08.2012    source источник
comment
Под строкой 1 вы подразумеваете: CGSize winSize = [[CCDirector sharedDirector] winSize]; ?   -  person Suny    schedule 03.08.2012
comment
Нет, строка с // (1) за ней... сводится к: [self addChild:infoMenu z:zIndex++];   -  person mmvie    schedule 03.08.2012
comment
Можете ли вы отладить и посмотреть, действительно ли в InfoMenu есть что-нибудь?   -  person Suny    schedule 03.08.2012
comment
Как я уже говорил в исходном вопросе, я уверен. Это значит, что я уже отладил его...   -  person mmvie    schedule 03.08.2012
comment
Что это за класс (т.е. подкласс UIView и т. д.), есть ли код для addChild::? Вы пытались сделать infoMenu свойством strong? Или попробовал NSLog([infoMenu description]), чтобы проверить, что он тоже содержит то, что вы хотите?   -  person Sam Clewlow    schedule 03.08.2012
comment
Этот код находится внутри CCLayer. addChild происходит от cocos2d. Превращение infoMenu в сильное свойство не имеет никакого значения, и infoMenu содержит то, что должно.   -  person mmvie    schedule 03.08.2012


Ответы (1)


Чтобы запустить Cocos2D в фоновом потоке, вам нужно создать новый EAGLContext. Так:

- (void)createMySceneInBackground
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    EAGLContext *k_context = [[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:[[[[CCDirector sharedDirector] openGLView] context] sharegroup]] autorelease];
    [EAGLContext setCurrentContext:k_context];

    if (infoMenu != nil) {
        infoMenu.position = ccp(winSize.width - kSSInfoPaddingX, winSize.height - kSSInfoPaddingY);
        [self addChild:infoMenu z:zIndex++]; // (1)
    }

    [pool release];
}

Удачи!

person Ricard Pérez del Campo    schedule 03.08.2012