2014-09-03 130 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] ;.希望它能幫助其他人!

從我這裏解決了我的問題。謝謝!