2015-05-15 18 views
6

Ho un timer in esecuzione quando il dispositivo entra in background perché voglio mantenere un controllo su una piccola quantità di dati nel mio servizio. Sto usando il seguente codice nel metodo applicationDidEnterBackground in App delegatoL'attività in background si interrompe quando il dispositivo è bloccato?

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]; 
}); 

Questo funziona assolutamente bene, fino a quando il dispositivo auto-serrature e poi il timer si ferma ticchettio. Qualche suggerimento su come impedire che ciò accada? Il tempo di live predefinito è di 5 minuti, quindi la maggior parte dei dispositivi sarà bloccata molto prima che questo torni anche una volta.

Grazie

+0

Forse si può stampare qualcosa nel gestore per vedere se siete a corto di tempo o se il problema è da qualche altra parte. – Andreas

+0

Sì, eseguo un NSLog quando viene chiamata la funzione e interrompe semplicemente la stampa quando il dispositivo si blocca automaticamente. Se blocco manualmente il dispositivo, continua a funzionare per un po 'ma alla fine si interrompe. Credo che potrei dover dare un'occhiata a una notifica push piuttosto che affidarmi a chiamare un servizio in background. –

+0

Voglio dire stampare qualcosa nel gestore di scadenza. Se ti dà solo un tempo di esecuzione extra in base a quando lo schermo verrebbe automaticamente bloccato automaticamente, lo scoprirai con un NSLog. – Andreas

risposta

2

Un paio di osservazioni:

  1. Mentre il signor H sottolinea, beginBackgroundTaskWithExpirationHandler ti dà solo tre minuti (180 secondi) nelle versioni iOS contemporanee. Quindi un tentativo di sparare un timer in cinque minuti non funzionerà.

    È possibile utilizzare [[UIApplication sharedApplication] backgroundTimeRemaining] per informazioni su quanto tempo è rimasto.

  2. Quando il dispositivo si blocca, le attività in background continuano. Non dovresti vedere l'app terminare. Se l'utente termina manualmente l'app tramite "tocca due volte il tasto home e scorri verso l'alto sulla schermata del commutatore di attività", ciò uccide le attività in background, ma non semplicemente il blocco del dispositivo.

  3. Alcuni commenti sul timer:

    • Il codice è l'aggiunta del timer a coda di sfondo. Generalmente non è necessario. Solo perché l'app si trova in uno stato di sfondo, puoi comunque continuare a utilizzare il ciclo di esecuzione principale per i timer e simili.

      Quindi, basta chiamare scheduledTimerWithTimeInterval dal thread principale e il gioco è fatto. Non ha senso usare un thread di lavoro GCD con un ciclo di esecuzione a meno che non sia assolutamente necessario (e anche in questo caso, potrei creare il mio thread personale e aggiungere un ciclo di esecuzione a quello).

      A proposito, se è assolutamente necessario pianificare il timer su una coda di invio in background, è probabilmente più semplice utilizzare il timer di invio. Elimina completamente il requisito del ciclo di esecuzione.

    • BTW, non è appropriato utilizzare scheduledTimerWithTimeInterval con addTimer. Chiama scheduledTimerWithTimeInterval per creare un timer e aggiungerlo al ciclo di esecuzione corrente. Si utilizza timerWithTimeInterval e quindi si chiama addTimer se si desidera aggiungerlo a un altro ciclo di esecuzione.

+0

Mi spiace postare ancora. Dopo aver rimosso il codice e appena eseguito il codice del timer, il timer non parte, o quando si avvia, quando poi porto di nuovo l'app in primo piano, è in uno stato congelato (suppongo che il timer stia ancora iniziando il filo). In entrambi i casi il codice iniziale è l'unico modo per ottenere l'effetto desiderato. Sembra che la curva di apprendimento xCode sia più ripida di quanto pensassi. Oh bene, grazie per le risposte in ogni caso. –

+0

No. Ho rimosso l'attività in background e ho spostato il timer nella coda principale. Questo mi ha dato la possibilità di eseguire un timer per tutto il tempo in cui l'app rimane sullo sfondo che è perfetta. Tuttavia, se rimuovo il comando ciclo di esecuzione, i timer cessano di funzionare e se li tengo dentro, l'app si blocca quando viene acquistata in primo piano. –

+0

Ah ah! i timer non sparavano perché avrei impostato timerWithTimeInterval piuttosto che scheduleTimerWithTimeInterval Modificato e ora funziona perfettamente e non si blocca quando si torna in primo piano. Grazie per tutto il tuo aiuto Rob! –