2015-05-15 15 views
6

Mam zegar działający, gdy urządzenie wchodzi w tło, ponieważ chcę, aby sprawdzić niewielką ilość danych w mojej usłudze. Używam następujący kod w metodzie applicationDidEnterBackground w app delegataZadanie w tle zatrzymuje się, gdy urządzenie jest zablokowane?

UIApplication *app = [UIApplication sharedApplication]; 

//create new uiBackgroundTask 
__block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
    [app endBackgroundTask:bgTask]; 
    bgTask = UIBackgroundTaskInvalid; 
}]; 

//and create new timer with async call: 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    //run function methodRunAfterBackground 
    NSString *server = [variableStore sharedGlobalData].server; 
    NSLog(@"%@",server); 
    if([server isEqual:@"_DEV"]){ 
     arrivalsTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(getArrivals) userInfo:nil repeats:YES]; 
    } 
    else { 
     arrivalsTimer = [NSTimer scheduledTimerWithTimeInterval:300 target:self selector:@selector(getArrivals) userInfo:nil repeats:YES]; 
    } 
    [[NSRunLoop currentRunLoop] addTimer:arrivalsTimer forMode:NSDefaultRunLoopMode]; 
    [[NSRunLoop currentRunLoop] run]; 
}); 

Działa to absolutnie w porządku, dopóki urządzenie samochodowych zamków, a następnie zegar przestaje odliczać. Wszelkie sugestie, jak temu zapobiec? Domyślny czas na żywo to 5 minut, więc większość urządzeń zostanie zablokowana na długo przed tym, zanim jeszcze raz się skasuje.

Dzięki

+0

Może można wydrukować coś w uchwycie, aby zobaczyć jeśli kończy się czas lub jeśli problem jest gdzieś indziej. – Andreas

+0

Tak, używam NSLog, gdy funkcja jest wywoływana i po prostu przestaje drukować, gdy urządzenie automatycznie blokuje się. Jeśli ręcznie zablokuję urządzenie, będzie ono działało przez jakiś czas, ale w końcu się zatrzyma. Sądzę, że będę musiał spojrzeć na powiadomienie push, zamiast polegać na wywołaniu usługi z tła. –

+0

Mam na myśli wydrukować coś w obsłudze expiration. Jeśli daje tylko dodatkowy czas wykonania w oparciu o to, kiedy ekran normalnie miałby automatyczną blokadę, zobaczysz to z NSLogiem. – Andreas

Odpowiedz

2

Kilka obserwacji:

  1. Jak Pan H wskazuje beginBackgroundTaskWithExpirationHandler daje ci tylko trzy minuty (180 sekund) w nowoczesnych wersjach iOS. Więc próba wystrzelenia timera w pięć minut nie zadziała.

    Możesz użyć [[UIApplication sharedApplication] backgroundTimeRemaining], aby dowiedzieć się, ile masz czasu.

  2. Po zablokowaniu urządzenia zadania w tle będą kontynuowane. Aplikacja nie powinna się kończyć. Jeśli użytkownik ręcznie zakończy aplikację, klikając dwukrotnie przycisk ekranu głównego i przesuń palcem w górę na ekranie przełączania zadań, co spowoduje wykonanie zadania w tle, ale nie tylko zablokowanie urządzenia.

  3. Kilka uwag na temat timerów:

    • Kod jest dodanie timera kolejce tła. Zwykle nie jest to konieczne. Tylko dlatego, że aplikacja działa w tle, możesz nadal używać głównej pętli dla timerów i tym podobnych.

      Po prostu zadzwoń scheduledTimerWithTimeInterval z głównego wątku i gotowe. Nie ma sensu używać wątku roboczego GCD z pętlą uruchamiania, chyba że jest to absolutnie konieczne (a nawet wtedy mógłbym utworzyć własny wątek i dodać do tego pętlę uruchamiania).

      Nawiasem mówiąc, jeśli absolutnie konieczne jest zaplanowanie timera na jakiejś kolejce wywołania w tle, prawdopodobnie łatwiej będzie użyć timera wysyłki. Całkowicie eliminuje to wymaganie pętli biegu.

    • Przy okazji nie należy używać scheduledTimerWithTimeInterval z addTimer. Zadzwoń pod numer scheduledTimerWithTimeInterval, aby utworzyć zegar i dodać go do bieżącej pętli uruchamiania. Używasz timerWithTimeInterval, a następnie dzwonisz pod numer addTimer, jeśli chcesz dodać go do innej pętli uruchamiania.

+0

Przepraszamy, aby opublikować ponownie. Po usunięciu kodu i uruchomieniu kodu timera, timer się nie uruchamia, lub kiedy się uruchamia, kiedy ponownie przynoszę aplikację na front, jest w stanie zamrożenia (myślę, że zegar wciąż trwa groźba). Tak czy inaczej, początkowy kod jest jedynym sposobem, w jaki mogę osiągnąć pożądany efekt. Wygląda na to, że krzywa uczenia xCode jest bardziej stroma, niż początkowo sądziłem. No cóż, w każdym razie dziękuję za odpowiedzi. –

+0

Nie. Usunąłem zadanie tła i przestawiłem zegar do głównej kolejki. To dało mi możliwość uruchomienia licznika czasu przez długi czas, w którym aplikacja pozostaje w tle, co jest idealne. Jeśli jednak usunę polecenie uruchamiania pętli, liczniki przestaną działać i jeśli je zatrzymam, aplikacja zawiesza się po zakupie na pierwszy plan. –

+0

Ah ha! timery nie uruchamiały się, ponieważ ustawiłem timerWithTimeInterval zamiast zaplanowałemTimerWithTimeInterval Zmieniono to i działa teraz idealnie i nie zatrzymuje się po powrocie na przód. Dzięki za pomoc Roba! –

Powiązane problemy