2013-09-25 77 views
14

我試圖在代碼中到處搜索:解釋文檔當它進入背景時它會發生什麼,或者它在某個時候甚至暫停,但無濟於事 - 是否有人指示我在啓用sprite kit的遊戲中進行背景推薦要做什麼?SpriteKit-多任務的正確方法

我應該打電話給scene.paused = YES,還是我該如何確認在後臺沒有繪圖,這樣我就可以避免被iOS終止而不允許我這麼做?

謝謝!

回答

14

LearnCocos2D所述here

的問題是當應用程序進入背景AVAudioSession不能活動。

該修復非常簡單,也適用於ObjectAL =>在應用程序處於後臺時將AVAudioSession設置爲非活動狀態,並在應用程序進入前臺時重新激活音頻會話。

簡化的AppDelegate與此修復程序看起來像這樣:

#import <AVFoundation/AVFoundation.h> 

... 

- (void)applicationWillResignActive:(UIApplication *)application 
{ 
    // prevent audio crash 
    [[AVAudioSession sharedInstance] setActive:NO error:nil]; 
} 

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    // prevent audio crash 
    [[AVAudioSession sharedInstance] setActive:NO error:nil]; 
} 

- (void)applicationWillEnterForeground:(UIApplication *)application 
{ 
    // resume audio 
    [[AVAudioSession sharedInstance] setActive:YES error:nil]; 
} 

PS:此修復程序將包含在狗頭包v7.0.3。

+1

第二個必要嗎? –

+0

這解決了它。很明顯,SpriteKit不能很好地處理音頻。 –

+0

此問題已在iOS8中解決。 iOS7並降低它的崩潰。 – rjm226

-4

Sprite Kit在移動到後臺時會自動暫停動畫計時器 - 您無需擔心自己的應用會因此而死亡。

+0

然而,顯然iOS終止了我的應用程序,由於EXC_BAD_ACCESS,但也顯示gpus_ReturnNotAllowedKillClient? –

+0

Sprite Kit _says_它會自動暫停其動畫計時器,但肯定存在問題。 – Kardasis

+0

我的背景也出現了'EXEC_BAD_ACCESS'錯誤 - 我的答案_seems_中的代碼已經修復了它,儘管我的應用程序現在確實不是那麼複雜...... – MassivePenguin

39

SpriteKit真的沒有被記錄,但可能是因爲它是如此新以至於相對較少的開發者已經實現它。 SpriteKit 應該暫停後臺動畫,但根據我的經驗(和harrym17's)它會導致內存訪問錯誤,並完全退出應用程序,而不是背景。

根據Apple Developer論壇的說法,這似乎是SpriteKit中的一個已知錯誤(它並不總是在背景時暫停動畫,因爲它應該)導致memory access errors as per harrym17's comment。這裏有一個簡單的解決方案已經爲我工作 - 我的應用程序一直崩潰背景時,並且因爲添加此代碼一切工作正常。

(在蘋果論壇上對此代碼的榮譽爲Keith Murray;據我所見,他還沒有發佈到SO上)。

AppDelegate.h,確保導入SpriteKit:

#import <SpriteKit/SpriteKit.h> 

AppDelegate.m,編輯您applicationWillResignActive方法:

- (void)applicationWillResignActive:(UIApplication *)application 
{ 
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 

    // pause sprite kit 
    SKView *view = (SKView *)self.window.rootViewController.view; 
    view.paused = YES; 
} 

這對您的applicationDidBecomeActive方法:

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 

    // resume sprite kit 
    SKView *view = (SKView *)self.window.rootViewController.view; 
    view.paused = NO; 
} 

有還有其他問題當通過AVAudioSession播放音頻時顯然是背景音樂;一個解決方法被提及in this thread

+0

這並不能防止崩潰(對我而言至少) –

+0

優秀。我可以證實這一點!如果你問我,應該在AppDelegate中爲默認的AppDelegate添加這個。另外,如果你在你的應用中使用聲音,將它與AVAudioSession修復結合在同一主題中。謝謝 – stvn

+0

我還沒有在這方面嘗試過,但你可能能夠使用NSTimer(請參閱http://stackoverflow.com/questions/1449035/how-do-i-use-nstimer)。我*有*使用NSTimer設置一個不同的變量,當應用程序變得活躍,所以它應該爲你工作。 – MassivePenguin

0

iPad似乎背景確定,但iPhone在背景精靈套件遊戲時肯定會崩潰。您必須手動完成此操作,自動切割片不會自動進行。

10

我想知道爲什麼在這個世界上這個看似簡單的解決方案導致我在應用程序啓動時崩潰,但這是因爲我有iAd運行。 所以,有一點要記住:@MassivePenguin的答案有效,但如果你有iAd去你將不得不通過subviewssubviews或顯然崩潰。

-(SKView*)getSKViewSubview{ 
    for (UIView* s in self.window.rootViewController.view.subviews) { 
     if ([s isKindOfClass:[SKView class]]) { 
      return (SKView*)s; 
     } 
    } 
    return nil; 
} 

- (void)applicationWillResignActive:(UIApplication *)application {  
    SKView* view = [self getSKViewSubview]; 

    if (view) { 
     view.paused = YES; 
    } 

} 

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    SKView* view = [self getSKViewSubview]; 

    if (view) { 
     view.paused = NO; 
    } 

} 
+0

您的解決方案確實爲我工作,謝謝! – user3033437

+0

做得好,非常簡單直接。謝謝加1 –

1

對於我沒有工作,沒有一個提供的解決方案。我確實找到了另一種方式如何做到這一點。

// In the AppDelegate 
- (void)applicationWillResignActive:(UIApplication *)application 
{ 
    if ([self.window.rootViewController isKindOfClass:[GameViewController class]]) { 
     GameViewController *vc = (GameViewController*)self.window.rootViewController; 
     [vc pauseGame]; 
     [vc.view addObserver:vc 
        forKeyPath:@"paused" 
        options:NSKeyValueObservingOptionNew 
        context:nil]; 
    } 
} 

// In the GameViewController 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    SKView *skView = (SKView*)self.view; 
    MainGame *mainGame = (MainGame*)skView.scene; 
    if ([keyPath isEqualToString:@"paused"] && 
     [[change objectForKey:NSKeyValueChangeNewKey] boolValue] == NO && 
     [mainGame isGameInProgress]) { 
     [self.view removeObserver:self forKeyPath:@"paused" context:nil]; 
     skView.paused = YES; 
    } 
}