SpriteKit: dźwięk w aplikacji iOS
Odtwarzanie dźwięku w grze napisanej w SpriteKit wygląda banalnie: jedna akcja, nazwa pliku, gotowe. Kłopot pojawia się, gdy aplikacja wychodzi na pierwszy plan i z niego schodzi, a system jednocześnie zarządza sesją audio dla całego urządzenia.
W opisywanej wersji systemu objawiało się to trzema problemami: zamknięciem aplikacji przy wyjściu, błędem przy próbie dezaktywacji sesji oraz ciszą po zakończeniu połączenia telefonicznego. Każdy z nich ma inną przyczynę i inne obejście.
Trzy objawy, jeden mechanizm
Aplikacja kończy działanie w momencie przejścia w tło albo przy zamykaniu, jeśli odtwarzała dźwięk akcją systemową. Dezaktywacja sesji audio kończy się błędem i nie przynosi efektu, choć kod wygląda poprawnie.
Po przerwaniu, na przykład przez przychodzące połączenie, dźwięk nie wraca. Gra działa dalej, obraz się odświeża, ale ścieżka dźwiękowa milknie do końca sesji. Użytkownik widzi grę, która „straciła głos”.
Skąd bierze się problem
Akcja odtwarzania dźwięku korzysta ze wspólnej sesji audio systemu. Ta sesja nie może pozostawać aktywna, gdy aplikacja jest w tle, a mimo to nie jest poprawnie zwalniana. Efektem jest konflikt przy zamykaniu procesu.
Drugi element to współdzielenie sesji z innymi aplikacjami. Jeśli w tle gra muzyka, próba wyłączenia własnej sesji zwraca błąd, bo system nie pozwala odebrać zasobu, który jest w użyciu. Kod musi to uwzględnić, a nie zakładać sukces pierwszego wywołania.
Wybór kategorii sesji ma znaczenie. Kategoria przeznaczona do tła pozwala grać własnym dźwiękom razem z muzyką z innej aplikacji i respektuje wyciszenie przełącznikiem. Kategoria odtwarzania przejmuje dźwięk na wyłączność, co w grze zwykle nie jest potrzebne.
Zarządzanie sesją
Praktyczne rozwiązanie polega na prowadzeniu sesji przez cały cykl życia aplikacji. Przy starcie ustawiana jest kategoria odpowiednia dla gry, sesja zostaje aktywowana, a przy przejściu w tło jest wyłączana. Po powrocie na pierwszy plan wraca.
Warto trzymać własną flagę stanu. Biblioteka graficzna nie wie, czy sesja jest aktywna, więc bez tej informacji próbuje odtwarzać dźwięki w momencie, gdy system już ich nie przyjmie. Flaga jest prostym bezpiecznikiem, który zapobiega tym próbom.
Dezaktywację wykonuj z opcją powiadomienia innych aplikacji, żeby muzyka w tle mogła wrócić po zakończeniu gry. Jeśli wywołanie zwróci błąd, powtarzaj je do skutku, zamiast przechodzić dalej z niespójnym stanem.
Przerwania i zmiany trasy
System wysyła powiadomienia o początku i końcu przerwania. Na początku sesję trzeba wyłączyć, na końcu aktywować ponownie, a informację o tym, czy aplikacja powinna wznowić odtwarzanie, potraktować jako wskazówkę, a nie polecenie.
- Obsłuż początek i koniec przerwania sesji.
- Reaguj na zmianę trasy dźwięku, np. po podłączeniu słuchawek.
- Nasłuchuj utraty i odtworzenia usług multimedialnych.
- Po odtworzeniu usług ustaw kategorię od nowa.
- Usuwaj obserwatorów przy zamykaniu aplikacji.
Zmiana trasy bywa pomijana, a potrafi zaskoczyć: po wyjęciu słuchawek dźwięk powinien wrócić na głośnik, a nie zamilknąć. Bez obsługi tego powiadomienia gra zachowuje się nieprzewidywalnie na różnych urządzeniach.
| Element | Co zrobić | Po czym poznać efekt |
|---|---|---|
| Start aplikacji | Ustaw kategorię i aktywuj sesję | Dźwięki grają od pierwszego ekranu |
| Przejście w tło | Dezaktywuj sesję z powiadomieniem | Brak błędu przy zamykaniu |
| Powrót na plan | Aktywuj sesję ponownie | Dźwięk wraca bez restartu |
| Przerwanie | Nasłuchuj powiadomień systemu | Gra milknie i wraca poprawnie |
| Zamknięcie | Usuń obserwatorów | Brak wywołań do zwolnionych obiektów |
Własny odtwarzacz zamiast akcji
Alternatywą jest odtwarzanie dźwięku przez własny odtwarzacz, wywoływane tą samą metodą co akcja. Dzięki temu kod gry się nie zmienia, a problem znika, bo nie korzystamy z wadliwej ścieżki systemowej.
Dane dźwięku trzymaj w pamięci, a nie w pliku, bo utworzenie odtwarzacza z gotowych danych jest szybsze. Każde odtworzenie powinno dostać własną instancję odtwarzacza, inaczej kolejny dźwięk przerwie poprzedni, zamiast zagrać równolegle.
Kompromisem jest rezygnacja z oczekiwania na koniec odtwarzania. W praktyce gry rzadko tego potrzebują, a uproszczenie kodu eliminuje całą klasę problemów z blokowaniem akcji i zwalnianiem zasobów.
Testowanie tego zachowania na symulatorze bywa mylące, bo przerwania trzeba wywołać sztucznie. Najpewniejszy test to urządzenie: w trakcie gry zadzwoń na telefon, zakończ połączenie i sprawdź, czy dźwięk wrócił bez restartu aplikacji.
Co dalej
Błąd prędzej czy później zostanie naprawiony w systemie, ale wzorzec zarządzania sesją zostaje aktualny. Aplikacja, która poprawnie oddaje sesję audio i odzyskuje ją po przerwaniu, zachowuje się dobrze także wtedy, gdy system przestanie mieć problem z zamknięciem. Warto więc traktować zarządzanie sesją jako stały element architektury, a nie jednorazowe obejście usterki.
Przeczytaj także
Komputer przestał działać: jak diagnozować
Czarny ekran, brak zasilania, restart — systematyczna diagnoza krok po kroku.
Dyski sieciowe NAS w domu: konfiguracja
Wybór dysków, macierz, udziały i zdalny dostęp bez zdawania się na chmurę.
Konsola: błąd autoryzacji płyty i co zrobić
Dlaczego gra przestaje się uruchamiać i jak sprawdzić nośnik oraz napęd.