我有一个"加载屏幕"使用"加载栏"。这个加载屏幕从我的服务器获取图像并将它们加载到CCSprites,所以我将在其他屏幕中使用它们。当加载屏幕正在下载图像并创建CCSprites时,我希望我的加载栏更新它的UI。 LoadingBar是CCNode的子类。
我知道我应该使用线程来更新UI,但问题是(据我所知)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!"];
}
}
基本上我所拥有的是一个背景灰色矩形作为背景和一个绿色的(正面),#34;填充"每次调用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 :(得分:1)
您应该更新主线程上的栏。而是将图像下载移动到后台线程。 NSData或NSURLRequest甚至具有异步方法。然后,当您完成下载图像后,在主线程上创建CCSprites作为最后一步。无论如何必须在主线程上创建精灵。
LearnCocos2D的答案(参见相关代码)加上:
解决!在getSpriteFromUrl中获取每个sprite后我睡了一觉。代码是[NSThread sleepForTimeInterval:0.2] ;.希望它可以帮助其他人!
从我这里解决了我的问题。谢谢!