2012-03-29 18 views
27

In ios5.0 con ARC, nel mio rootviewcontroller, chiamo un metodo in un oggetto gestore sicurezza che è trattenuto dal delegato dell'app. In questo metodo ho impostato il timer come sottoNSTimer non attiva il selettore

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self 
             selector:@selector(updateModel:) userInfo:str repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 

Tuttavia, questo non attiva mai il selettore. updateModel: non viene mai chiamato. Cosa potrebbe essere sbagliato? C'è un altro modo più efficiente che posso fare senza usare NStimer?

risposta

10

Sembra che tu sia un po 'confuso con la tua variabile timer.

Si inizializza un nuovo timer ma non lo si sta effettivamente utilizzando. Vuoi usare il timer che hai inizializzato o ti vuoi ApplicationDelegate.timer?

Ecco le due soluzioni possibili.

Option One (supponendo che si dispone di un'istanza di classe dal titolo ApplicationDelegate e che ha una proprietà timer):

ApplicationDelegate.timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(updateModel:) userInfo:str repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:ApplicationDelegate.timer forMode:NSRunLoopCommonModes]; 

Opzione due:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(updateModel:) userInfo:str repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 
+0

scusa ab l'errore nel post .. L'ho modificato per riflettere il modo in cui lo sto facendo. Sto usando il secondo modo in cui hai menzionato ... Non funziona ancora. – inforeqd

+20

Il secondo modo non è corretto. Sta tentando di aggiungere il timer due volte. 'scheduledTimerWithTimeInterval: ...' ha già aggiunto il timer. Assicurati di eseguirlo sul thread principale. –

+0

c'è un modo per scoprire in quale thread viene aggiunto il timer? Penso che sia il thread principale che sto aggiungendo a ... – inforeqd

5

Questa linea ha diversi problemi:

[[NSRunLoop currentRunLoop] addTimer:ApplicationDelegate.timer forMode:NSRunLoopCommonModes]; 

In primo luogo, non dovrebbe essere richiesto affatto. -scheduledTimerWithTimeInterval:... aggiunge già il timer al runloop. Non è necessario aggiungerlo di nuovo.

In secondo luogo, la variabile locale timer non è correlata alla proprietà ApplicationDelegate.timer (che è presumibilmente nil a questo punto).

Se stai parlando con l'applicazione delegare così tanto che hai creato qualcosa chiamato ApplicationDelegate (una macro globale?), Stai parlando troppo. Il delegato dell'applicazione è il delegato per l'applicazione; assiste nell'applicazione di avvio, arresto e risposta agli eventi di sistema. Il delegato dell'applicazione non è un luogo in cui memorizzare le variabili globali. In ogni caso, un timer non è assolutamente il tipo di cosa che devi recuperare da un altro oggetto.

+0

mi dispiace per l'errore nel post .. L'ho modificato per riflettere il modo in cui lo sto facendo .... Non funziona ancora. Informazioni sul tuo commento sull'utilizzo del delegato dell'applicazione .. Ho un modello che creo dopo aver analizzato una risposta al servizio web. Devo conservare il modello per tutte le viste nell'applicazione. Pertanto, ritengo che il modello debba essere trattenuto dal delegato dell'applicazione altrimenti, non sono sicuro di dove altro posso tenerlo per tutte le viste da utilizzare. – inforeqd

+1

È possibile passare il modello ai controller della vista quando li si costruisce oppure è possibile posizionare gli oggetti del modello in un singleton. Non dovresti appenderli al delegato dell'app. Ciò rende molto difficile il riutilizzo del codice e complica il delegato dell'app (che ha una propria funzione da eseguire non correlata alla memorizzazione dei dati). –

8

prendo lo stesso problema e ho fuoco timer in coda principale per risolverlo:

[NSURLConnection sendAsynchronousRequest:request queue:_operationQueue 
    completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){ 
     [self loopUpUpdateStart]; 
}]; 

-(void)loopUpUpdateStart{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 

     _loopTimerForUpRevision = 
      NSTimer scheduledTimerWithTimeInterval: kNetworkLoopIntervalUpRev 
              target: self 
             selector: @selector(myCoolMethod) 
             userInfo: nil 
             repeats: YES]; 
     TRACE(@"Start Up updates"); 
    }); 
} 
105

Potrebbe anche essere un problema di threading:

se

[NSThread isMainThread] 

è falsa quindi avviare il timer come questo:

dispatch_async(dispatch_get_main_queue(), ^{ 
     timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(tick:) userInfo:nil repeats:YES]; 
    }) 
+0

+1, grazie ... questo ha fatto il trucco! – Joe

+1

Grazie! Puoi spiegare per favore qual è il problema del threading? – JohnH

+4

Il timer viene eseguito solo nel thread principale (UI) correttamente. Se si tenta di avviare il timer in un altro thread rispetto al thread principale, non verrà generato. – tmanthey