2014-05-12 12 views
7

Ho un frammento di codice come questo:NSTimer non sparare selettore quando aggiunto con scheduledTimerWithTimeInterval

m_timer = [NSTimer scheduledTimerWithTimeInterval:timeOutInSeconds 
                 target:self 
                selector:@selector(activityIndicatorTimer:) 
                userInfo:nil 
                 repeats:NO]; 

Quando io lo chiamo in questo modo il selettore non viene licenziato dopo le timeOutInSeconds dato. Tuttavia, se lo modifico come il seguente, il selettore viene chiamato due volte.

NSLog(@"Timer set"); 
m_timer = [NSTimer scheduledTimerWithTimeInterval:timeOutInSeconds 
               target:self 
              selector:@selector(activityIndicatorTimer:) 
              userInfo:nil 
               repeats:NO]; 
[[NSRunLoop currentRunLoop] addTimer:m_timer forMode:NSRunLoopCommonModes]; 

Qualcuno potrebbe offrire qualche suggerimento su ciò che probabilmente sto facendo male?

sto utilizzando XCode 5.1, e sulla base 7.1.1 iPhone 4S

+4

La mia ipotesi è che stai deposizione delle uova di questo timer fuori un thread in background senza runloop (la maggior parte non hanno uno) 'scheduledTimerWithTimeInterval' deve essere chiamato da un thread con un runloop (di solito il thread principale). Per aggiungere il timer al runloop come sei, dovresti usare "timerWithTimeInterval ...". –

+0

Chiama '[m_timer fire]' dopo la prima opzione –

+0

Grazie David, credo che tu avessi ragione. Con il tuo aiuto sembra che ho trovato il problema. Se desideri inviarlo come risposta, piuttosto che commentare, posso accettarlo. – xceph

risposta

29

chiamata questo timer nel thread principale:

dispatch_async(dispatch_get_main_queue(), ^{ 
    m_timer = [NSTimer scheduledTimerWithTimeInterval:timeOutInSeconds 
                target:self 
               selector:@selector(activityIndicatorTimer:) 
               userInfo:nil 
                repeats:NO]; 
}); 
1

hai 3 opzioni timer creazione, come stati di Apple nel doc:

  • Utilizzare i scheduledTimerWithTimeInterval:invocation:repeats: oppure scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: classe metodo per creare il timer e programmarlo sul ciclo di esecuzione corrente in modalità predefinita.
  • Utilizzare il timerWithTimeInterval:invocation:repeats: metodo o timerWithTimeInterval:target:selector:userInfo:repeats: classe per creare l'oggetto timer senza pianificazione su un loop di corsa. (Dopo creandola, è necessario aggiungere il timer per un ciclo corsa manualmente chiamando il addTimer: forMode:. Metodo dell'oggetto NSRunLoop corrispondente)
  • Assegnare il timer e inizializzare usando il metodo initWithFireDate:interval:target:selector:userInfo:repeats:. (Dopo la creazione, è necessario aggiungere il timer per un ciclo corsa manualmente chiamando l'addTimer: forMode:. Metodo della corrispondente NSRunLoop oggetto)

Il metodo si utilizza già pianificazioni le timer sul loop corrente e non si dovrebbe programmare un'altra volta. Secondo me il problema è altrove, provare (per semplificare) a inserire un valore fisso invece di timeOutInSeconds.
Anche il modo più comune per chiamare qualcosa dopo un ritardo specifico (che non deve ripetere) è l'uso dispatch_after:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     //YOUR CODE 
    }); 

Quando la figura 2 è un intervallo arbitrario (in questo caso 2 secondi).

+0

Questo in realtà non risponde alla domanda. –