2014-09-03 90 views
0

我有一个“加载屏幕”与“加载栏”。这个加载屏幕从我的服务器获取图像并将它们加载到CCSprites,因此我将在其他屏幕中使用它们。在加载屏幕下载图像并创建CCSprites时,我希望我的加载栏能够更新它的UI。 LoadingBar是一个CCNode子类。我知道我应该使用线程来更新用户界面,但问题是(据我所知)Cocos2D节点不是线程安全的,所以当我使用下面的代码时,它确实更新了用户界面,但随后精灵确实不加载:Cocos2D更新UI与线程

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, kNilOptions), ^{ 
    // go do something asynchronous... 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // update UI 
    }); 
}); 

我试过很多东西,但是我不能解决这个问题。请帮助:)

这里是一个让我LoadingBar更新代码:

-(void)makeStep{ 
int actualPersentage = 100 * (numSteps - numStepsToGo + 1)/numSteps; 
int objectAtIndex = MAX(0, numSteps - numStepsToGo); 
persentageLabel.string = [NSString stringWithFormat:@"%i%% %@", actualPersentage, [steps objectAtIndex:objectAtIndex]]; 
[frontground setTextureRect:CGRectMake(0, 0, frontground.textureRect.size.width + (200/numSteps), 40)]; 
frontground.position = ccp(initialPosition + (frontground.contentSize.width/2) - (background.contentSize.width/2), frontground.position.y); 
numStepsToGo --; 

if(numStepsToGo == 0){ 
    [frontground setTextureRect:CGRectMake(0, 0, 200, 40)]; 
    persentageLabel.string = [NSString stringWithFormat:@"All loaded correctly!"]; 
} 
} 

基本上我有一个背景灰色矩形背景和一个绿色的(frontground)认为,“填充”的背景每次调用makeStep。

下面是代码示例,其中我分析JSON和在我的LoadingBar应该更新:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, kNilOptions), ^{ 
... 
CCSprite *ssButtonStart = [self getSpriteFromUrl:[startScreenData objectForKey:@"SSimg_button_start"]]; 
CCSprite *ssButtonExit = [self getSpriteFromUrl:[startScreenData objectForKey:@"SSimg_button_exit"]]; 
CCSprite *ssBackground = [self getSpriteFromUrl:[startScreenData objectForKey:@"SSimg_background"]]; 
self.gameProperties.slBackground = ssBackground; 
self.gameProperties.slButtonExit = ssButtonExit; 
self.gameProperties.slButtonStart = ssButtonStart; 
NSLog(@"Start Screen Loading done!"); 
dispatch_async(dispatch_get_main_queue(), ^{ 
    [self updateStep]; 
}); 
... 
dispatch_async(dispatch_get_main_queue(), ^{ 
    [self updateStep]; 
}); 
//Etc. 

代码,我得到的图像,并转换成CCSprite:

-(CCSprite*)getSpriteFromUrl:(NSString*)stringUrl{ 
__block NSData *imageData; 
__block CCSprite *sprite; 
    imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:stringUrl]]; 
     //NSLog(@"string imageData: %@", imageData); 
     UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageWithData: imageData]]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     CCTexture2D *texture = [[CCTexture2D alloc] initWithCGImage:imView.image.CGImage resolutionType:kCCResolutionUnknown]; 
     if(texture != nil){ 
      sprite = [[CCSprite alloc] init]; 
      sprite = [[CCSprite alloc] initWithTexture:texture]; 
     }else{ 
      [self showError:@"Some textures didn't load correctly. Please try again!"]; 
     } 
     // update UI 
    }); 
return sprite; 
} 

我使用的是iOS 7和Cocos2D 2.0

+0

您应该更新主线程上的栏。而是将图像下载到后台线程。 NSData或NSURLRequest甚至包含异步方法。然后,当您完成下载图像时,在主线程上创建CCSprites作为最后一步。无论如何,精灵必须在主线程上创建。 – LearnCocos2D 2014-09-03 08:21:19

+0

谢谢你的回答。我已经尝试了你的建议,但没有成功。我使用已更改的代码和获取图像的方法更新问题。你能告诉我我错在哪里吗? – aramusss 2014-09-03 09:09:48

+0

解决!在getSpriteFromUrl中获得每个精灵之后,我睡了一觉。代码是'[NSThread sleepForTimeInterval:0.2];'。希望它能帮助其他人! – aramusss 2014-09-03 09:56:39

回答

1

您应该更新主线程上的栏。而是将图像下载到后台线程。 NSData或NSURLRequest甚至包含异步方法。然后,当您完成下载图像时,在主线程上创建CCSprites作为最后一步。无论如何,精灵必须在主线程上创建。

这个答案从LearnCocos2D(见代码有问题)加:

解决了!在getSpriteFromUrl中获得每个精灵之后,我进行了一次睡眠。代码是[NSThread sleepForTimeInterval:0.2] ;.希望它能帮助其他人!

从我这里解决了我的问题。谢谢!