Uruchamianie procesów w tle w systemie iOS za pomocą zadań
Najprostszym sposobem wykonywania w tle w systemie iOS jest podzielenie wymagań dotyczących wykonywania w tle na zadania i uruchamianie zadań w tle. Zadania są objęte ścisłym limitem czasu, a zwykle około 600 sekund (10 minut) czasu przetwarzania po przeniesieniu aplikacji do tła w systemie iOS 6 i mniej niż 10 minut w systemie iOS 7 lub nowszym.
Zadania w tle można podzielić na trzy kategorie:
- Zadania Sejf w tle — wywoływane w dowolnym miejscu w aplikacji, w której masz zadanie, którego nie chcesz przerywać, jeśli aplikacja wejdzie w tle.
- DidEnterBackground Tasks — wywoływana podczas
DidEnterBackground
metody cyklu życia aplikacji w celu ułatwienia czyszczenia i zapisywania stanu. - Transfery w tle (iOS 7+) — specjalny typ zadania w tle używanego do wykonywania transferów sieciowych w systemie iOS 7. W przeciwieństwie do zwykłych zadań transfery w tle nie mają wstępnie określonego limitu czasu.
Bezpieczne w tle i DidEnterBackground
zadania są bezpieczne do użycia zarówno w systemach iOS 6, jak i iOS 7, z niewielkimi różnicami. Przyjrzyjmy się tym dwóm typom zadań bardziej szczegółowo.
Tworzenie zadań Sejf w tle
Niektóre aplikacje zawierają zadania, które nie powinny być przerywane przez system iOS, jeśli stan zmiany aplikacji. Jednym ze sposobów ochrony tych zadań przed przerwaniem jest zarejestrowanie ich w systemie iOS jako długotrwałych zadań. Możesz użyć tego wzorca w dowolnym miejscu w aplikacji, w którym nie chcesz przerywać zadania, jeśli użytkownik umieści aplikację w tle. Doskonałym kandydatem do tego wzorca są zadania, takie jak wysyłanie informacji o rejestracji nowego użytkownika do serwera lub weryfikowanie informacji logowania.
Poniższy fragment kodu przedstawia rejestrowanie zadania do uruchomienia w tle:
nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});
//runs on main or background thread
FinishLongRunningTask(taskID);
UIApplication.SharedApplication.EndBackgroundTask(taskID);
Proces rejestracji łączy zadanie z unikatowym identyfikatorem, taskID
a następnie opakowuje je w dopasowywanie BeginBackgroundTask
i EndBackgroundTask
wywołania. Aby wygenerować BeginBackgroundTask
identyfikator, tworzymy wywołanie metody w UIApplication
obiekcie, a następnie uruchamiamy długotrwałe zadanie, zwykle w nowym wątku. Po zakończeniu zadania wywołujemy EndBackgroundTask
i przekazujemy ten sam identyfikator. Jest to ważne, ponieważ system iOS zakończy działanie aplikacji, jeśli BeginBackgroundTask
wywołanie nie ma pasującego EndBackgroundTask
elementu .
Ważne
Zadania bezpieczne w tle mogą być uruchamiane w wątku głównym lub w wątku w tle, w zależności od potrzeb aplikacji.
Wykonywanie zadań podczas polecenia DidEnterBackground
Oprócz zapewnienia bezpieczeństwa w tle długotrwałego zadania rejestracja może służyć do uruchamiania zadań w tle, ponieważ aplikacja jest umieszczana w tle. System iOS udostępnia metodę zdarzenia w klasie AppDelegate o nazwie DidEnterBackground
, która może służyć do zapisywania stanu aplikacji, zapisywania danych użytkownika i szyfrowania poufnej zawartości przed wejściem aplikacji w tle. Aplikacja ma około pięć sekund na powrót z tej metody lub zostanie zakończona. W związku z tym zadania oczyszczania, które mogą potrwać ponad pięć sekund, mogą być wywoływane z wewnątrz DidEnterBackground
metody. Te zadania muszą być wywoływane w osobnym wątku.
Proces jest prawie identyczny z procesem rejestrowania długotrwałego zadania. Poniższy fragment kodu ilustruje to w akcji:
public override void DidEnterBackground (UIApplication application) {
nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});
new Task ( () => {
DoWork();
UIApplication.SharedApplication.EndBackgroundTask(taskID);
}).Start();
}
Zaczynamy od zastąpienia DidEnterBackground
metody w AppDelegate
pliku , gdzie rejestrujemy zadanie za pomocą BeginBackgroundTask
metody , tak jak w poprzednim przykładzie. Następnie zduplikujemy nowy wątek i wykonamy nasze długotrwałe zadanie. Należy pamiętać, że EndBackgroundTask
wywołanie jest teraz wykonywane z wewnątrz długotrwałego zadania, ponieważ DidEnterBackground
metoda zostanie już zwrócona.
Ważne
System iOS używa mechanizmu watchdog, aby upewnić się, że interfejs użytkownika aplikacji pozostaje dynamiczny. Aplikacja, która spędza zbyt dużo czasu, DidEnterBackground
przestanie odpowiadać w interfejsie użytkownika. Uruchamianie zadań do uruchamiania w tle pozwala DidEnterBackground
na powrót w odpowiednim czasie, zachowanie reakcji interfejsu użytkownika i zapobieganie zabijaniu aplikacji przez watchdog.
Obsługa limitów czasu zadania w tle
System iOS nakłada ścisłe limity czasu działania zadania w tle, a jeśli EndBackgroundTask
wywołanie nie zostanie wykonane w wyznaczonym czasie, aplikacja zostanie zakończona. Dzięki śledzeniu pozostałego czasu w tle i używaniu procedur obsługi wygasania w razie potrzeby możemy uniknąć zakończenia aplikacji przez system iOS.
Uzyskiwanie dostępu do pozostałego czasu w tle
Jeśli aplikacja z zarejestrowanymi zadaniami zostanie przeniesiona w tle, zarejestrowane zadania zostaną uruchomione około 600 sekund. Możemy sprawdzić, ile czasu zadanie musi wykonać przy użyciu właściwości statycznej BackgroundTimeRemaining
UIApplication
klasy. Poniższy kod da nam czas (w sekundach), że nasze zadanie w tle pozostało:
double timeRemaining = UIApplication.SharedApplication.BackgroundTimeRemaining;
Unikanie kończenia działania aplikacji przy użyciu procedur obsługi wygasania
Oprócz udzielenia dostępu do BackgroundTimeRemaining
właściwości system iOS zapewnia bezproblemowy sposób obsługi wygaśnięcia czasu w tle za pośrednictwem programu obsługi wygasania wygasania. Jest to opcjonalny blok kodu, który zostanie wykonany, gdy czas przydzielony do zadania wkrótce wygaśnie. Kod w wywołaniach programu obsługi wygasania EndBackgroundTask
i przekazuje identyfikator zadania, który wskazuje, że aplikacja działa dobrze i uniemożliwia systemowi iOS kończenie działania aplikacji, nawet jeśli zadanie kończy się z upływem czasu. EndBackgroundTask
należy wywołać program obsługi wygasania, a także w normalnym przebiegu wykonywania.
Procedura obsługi wygasania jest wyrażana jako funkcja anonimowa przy użyciu wyrażenia lambda, jak pokazano poniżej:
Task.Factory.StartNew( () => {
//expirationHandler only called if background time allowed exceeded
var taskId = UIApplication.SharedApplication.BeginBackgroundTask(() => {
Console.WriteLine("Exhausted time");
UIApplication.SharedApplication.EndBackgroundTask(taskId);
});
while(myFlag == true)
{
Console.WriteLine(UIApplication.SharedApplication.BackgroundTimeRemaining);
myFlag = SomeCalculationNeedsMoreTime();
}
//Only called if loop terminated due to myFlag and not expiration of time
UIApplication.SharedApplication.EndBackgroundTask(taskId);
});
Chociaż programy obsługi wygasania nie są wymagane do uruchomienia kodu, należy zawsze używać programu obsługi wygasania z zadaniem w tle.
Zadania w tle w systemie iOS 7 lub nowszym
Największą zmianą w systemie iOS 7 w odniesieniu do zadań w tle nie jest sposób implementowania zadań, ale po uruchomieniu.
Przypomnij sobie, że przed systemem iOS 7 zadanie uruchomione w tle miało 600 sekund do ukończenia. Jednym z powodów tego limitu jest to, że zadanie uruchomione w tle spowoduje, że urządzenie obudziłoby się przez czas trwania zadania:
Przetwarzanie w tle systemu iOS 7 jest zoptymalizowane pod kątem dłuższego czasu pracy baterii. W systemie iOS 7 tło staje się oportunistyczne: zamiast utrzymywać stan uśpienia urządzenia, podzadania, gdy urządzenie przechodzi w stan uśpienia, a zamiast tego wykonywać przetwarzanie we fragmentach, gdy urządzenie budzi się w celu obsługi połączeń telefonicznych, powiadomień, przychodzących wiadomości e-mail i innych typowych przerw. Poniższy diagram zawiera szczegółowe informacje o tym, jak można podzielić zadanie:
Ponieważ czas wykonywania zadania nie jest już ciągły, zadania wykonujące transfery sieciowe muszą być obsługiwane inaczej w systemie iOS 7. Deweloperzy są zachęcani do korzystania z interfejsu NSURlSession
API do obsługi transferów sieciowych. Następna sekcja zawiera omówienie transferów w tle.
Transfery w tle
Szkielet transferów w tle w systemie iOS 7 to nowy NSURLSession
interfejs API. NSURLSession
umożliwia tworzenie zadań w celu:
- Transferowanie zawartości za pośrednictwem przerw w działaniu sieci i urządzeń.
- Przekazywanie i pobieranie dużych plików ( usługa transferu w tle).
Przyjrzyjmy się bliżej temu, jak to działa.
NSURLSession API
NSURLSession
to zaawansowany interfejs API do przesyłania zawartości za pośrednictwem sieci. Udostępnia zestaw narzędzi do obsługi transferu danych przez przerwy w działaniu sieci i zmian w stanach aplikacji.
Interfejs NSURLSession
API tworzy jedną lub kilka sesji, co z kolei powoduje zduplikowania zadań do bloków transferowych powiązanych danych w całej sieci. Zadania są uruchamiane asynchronicznie, aby szybko i niezawodnie przesyłać dane. Ponieważ NSURLSession
jest asynchroniczna, każda sesja wymaga bloku obsługi ukończenia, aby poinformować system i aplikację o zakończeniu transferu.
Aby wykonać transfer sieciowy, który jest prawidłowy zarówno w systemie iOS 7, jak i po iOS 7, sprawdź, czy element NSURLSession
jest dostępny do przesyłania w kolejce, i użyj zwykłego zadania w tle do wykonania transferu, jeśli nie jest:
if ([NSURLSession class]) {
// Create a background session and enqueue transfers
}
else {
// Start a background task and transfer directly
// Do NOT make calls to update the UI here!
}
Ważne
Unikaj wykonywania wywołań w celu zaktualizowania interfejsu użytkownika z poziomu tła w kodzie zgodnym z systemem iOS 6, ponieważ system iOS 6 nie obsługuje aktualizacji interfejsu użytkownika w tle i zakończy działanie aplikacji.
Interfejs NSURLSession
API zawiera bogaty zestaw funkcji do obsługi uwierzytelniania, zarządzania nieudanymi transferami i raportowania po stronie klienta — ale nie po stronie serwera — błędów. Ułatwia ona łączenie przerw w czasie wykonywania zadań wprowadzonych w systemie iOS 7, a także zapewnia obsługę szybkiego i niezawodnego przesyłania dużych plików. W następnej sekcji przedstawiono tę drugą funkcję.
Usługa transferu w tle
Przed systemem iOS 7 przekazywanie lub pobieranie plików w tle było zawodne. Zadania w tle mają ograniczony czas do uruchomienia, ale czas potrzebny na transfer pliku różni się w zależności od sieci i rozmiaru pliku. W systemie iOS 7 możemy użyć elementu NSURLSession
, aby pomyślnie przekazać i pobrać duże pliki. Określony NSURLSession
typ sesji, który obsługuje transfery sieciowe dużych plików w tle, jest znany jako usługa transferu w tle.
Transfery inicjowane przy użyciu usługi transferu w tle są zarządzane przez system operacyjny i zapewniają interfejsy API do obsługi uwierzytelniania i błędów. Ponieważ transfery nie są powiązane przez dowolny limit czasu, mogą służyć do przekazywania lub pobierania dużych plików, automatycznej aktualizacji zawartości w tle i nie tylko. Aby uzyskać szczegółowe informacje na temat implementowania usługi, zapoznaj się z przewodnikiem transferu w tle.
Usługa transferu w tle jest często sparowana z funkcjami pobierania w tle lub powiadomień zdalnych, aby ułatwić aplikacjom odświeżanie zawartości w tle. W dwóch następnych sekcjach przedstawimy koncepcję rejestrowania całych aplikacji do uruchamiania w tle zarówno w systemach iOS 6, jak i iOS 7.