Come uso NSTimer?


344

Come si usa un NSTimer? Qualcuno può darmi istruzioni passo dopo passo?


1
ho ricevuto informazioni parametriche su pravinmagdum.wordpress.com/2010/12/30/how-to-use-nstimer date un'occhiata .. potrebbe essere utile per voi

Risposte:


616

Innanzi tutto, vorrei attirare la vostra attenzione sulla documentazione Cocoa / CF (che è sempre un ottimo primo approdo). I documenti di Apple hanno una sezione nella parte superiore di ogni articolo di riferimento chiamato "Guide companion", che elenca le guide per l'argomento documentato (se presente). Ad esempio, con NSTimer, la documentazione elenca due guide companion:

Per la tua situazione, l'articolo Argomenti di programmazione del timer è probabilmente il più utile, mentre gli argomenti di threading sono correlati ma non più direttamente correlati alla classe che viene documentata. Se dai un'occhiata all'articolo Argomenti di programmazione del timer, è diviso in due parti:

  • Timer
  • Utilizzando i timer

Per gli articoli che assumono questo formato, c'è spesso una panoramica della classe e del suo uso, e poi del codice di esempio su come usarlo, in questo caso nella sezione "Uso dei timer". Ci sono sezioni su "Creazione e pianificazione di un timer", "Arresto di un timer" e "Gestione della memoria". Dall'articolo, la creazione di un timer programmato e non ripetibile può essere eseguita in questo modo:

[NSTimer scheduledTimerWithTimeInterval:2.0
    target:self
    selector:@selector(targetMethod:)
    userInfo:nil
    repeats:NO];

Ciò creerà un timer che viene attivato dopo 2,0 secondi e chiama targetMethod: su selfdi un argomento, che è un puntatore alla NSTimeristanza.

Se vuoi quindi esaminare più dettagliatamente il metodo, puoi fare riferimento ai documenti per ulteriori informazioni, ma c'è anche una spiegazione intorno al codice.

Se si desidera arrestare un timer che si ripete (o interrompere un timer che non si ripete prima che si attivi), è necessario mantenere un puntatore NSTimerall'istanza creata; spesso questa dovrà essere una variabile di istanza in modo da poter fare riferimento ad essa in un altro metodo. È quindi possibile chiamare invalidatel' NSTimeristanza:

[myTimer invalidate];
myTimer = nil;

E 'anche buona norma nilla variabile di istanza (ad esempio se il metodo che invalida il timer è chiamato più di una volta e la variabile di istanza non è stata impostata per nile laNSTimer istanza è stata deallocata, genererà un'eccezione).

Nota anche il punto sulla gestione della memoria nella parte inferiore dell'articolo:

Poiché il ciclo di esecuzione mantiene il timer, dal punto di vista della gestione della memoria non è in genere necessario mantenere un riferimento a un timer dopo averlo pianificato . Dal momento che il timer viene passato come argomento quando si specifica il suo metodo come selettore, è possibile invalidare un timer ripetuto quando appropriato all'interno di quel metodo . In molte situazioni, tuttavia, si desidera anche l'opzione di invalidare il timer, forse anche prima che inizi. In questo caso, è necessario mantenere un riferimento al timer, in modo da poter inviare un messaggio non valido ogni volta che è necessario. Se si crea un timer non programmato (consultare "Timer non programmati"), è necessario mantenere un riferimento forte al timer (in un ambiente contato da riferimenti, lo si conserva) in modo che non venga deallocato prima di utilizzarlo.


Ok, una domanda, cosa inserirò come codice che verrebbe eseguito ogni due secondi?
lab12

Passeresti YESper repeats:quando chiami scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:. Se lo fai, assicurati di mantenere un riferimento NSTimerall'istanza (viene restituito dal metodo) e segui il punto su Gestione della memoria come ho dettagliato sopra.
Alex Rozanski,

No, dove metterei il mio codice che verrebbe avviato ogni 2 secondi? Ad esempio, supponiamo che volessi emettere un segnale acustico ogni 2 secondi. dove metterei il codice del rumore del bip ..?
lab12,

Nel metodo specificato con targete selector. Ad esempio, se il tuo obiettivo è selfe il selettore è timerMethod:, il metodo chiamato quando il timer scatta è timerMethod:definito su self. È quindi possibile inserire qualsiasi codice desiderato in quel metodo e il metodo verrà chiamato ogni volta che scatta il timer. Si noti che il metodo chiamato quando viene attivato il timer (che si passa come selector:) può accettare solo un argomento (che quando chiamato è un puntatore NSTimerall'istanza).
Alex Rozanski,

Spiacente, significa "definito self"
Alex Rozanski,

331

ci sono un paio di modi per usare un timer:

1) timer programmato e utilizzo del selettore

NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
                      target: self
                      selector:@selector(onTick:)
                      userInfo: nil repeats:NO];
  • se si imposta la ripetizione su NO, il timer attenderà 2 secondi prima di avviare il selettore e successivamente si fermerà;
  • se ripeti: SÌ, il timer si avvierà immediatamente e ripeterà la chiamata al selettore ogni 2 secondi;
  • per interrompere il timer si chiama il metodo -invalidate del timer: [t invalidato];

Come nota a margine, invece di utilizzare un timer che non si ripete e chiama il selettore dopo un intervallo specificato, è possibile utilizzare una semplice istruzione come questa:

[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];

questo avrà lo stesso effetto del codice di esempio sopra; ma se vuoi chiamare il selettore ogni ennesima volta, usi il timer con ripetizioni: SÌ;

2) timer autoprogrammato

NSDate *d = [NSDate dateWithTimeIntervalSinceNow: 60.0];
NSTimer *t = [[NSTimer alloc] initWithFireDate: d
                              interval: 1
                              target: self
                              selector:@selector(onTick:)
                              userInfo:nil repeats:YES];

NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer:t forMode: NSDefaultRunLoopMode];
[t release];
  • questo creerà un timer che si avvierà da solo in una data personalizzata da te specificata (in questo caso, dopo un minuto) e si ripete ogni secondo

3) timer non programmato e utilizzo dell'invocazione

NSMethodSignature *sgn = [self methodSignatureForSelector:@selector(onTick:)];
NSInvocation *inv = [NSInvocation invocationWithMethodSignature: sgn];
[inv setTarget: self];
[inv setSelector:@selector(onTick:)];

NSTimer *t = [NSTimer timerWithTimeInterval: 1.0
                      invocation:inv 
                      repeats:YES];

e successivamente, avvia il timer manualmente ogni volta che è necessario in questo modo:

NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer: t forMode: NSDefaultRunLoopMode];



E come nota, onTick: il metodo è simile al seguente:

-(void)onTick:(NSTimer *)timer {
   //do smth
}

Ok, ma vedi che voglio ridurre la trasparenza della mia app, quindi non so come applicarla con NSTimer
lab12

24
caspita, queste persone oggi .. vota giù da me perché non l'hai specificato dall'inizio e lasciaci scrivere invano!
Woofy,

28
Non hai scritto invano. Questa è una buona informazione!
willc2,

Nel metodo 2, "timer autoprogrammato", come posso interrompere il timer quando lo desidero?
Satyam,

1
@Satyamsvv, puoi interrompere il timer invocando, ad esempio un altro metodo con: [timer invalidato]; timer = zero;
Kimpoy,

59

Qualcosa come questo:

NSTimer *timer;

    timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
                     target: self
                     selector: @selector(handleTimer:)
                     userInfo: nil
                     repeats: YES];

14
Ancora forte ... anche il 2014!
Muruganandham K

5
#import "MyViewController.h"

@interface MyViewController ()

@property (strong, nonatomic) NSTimer *timer;

@end

@implementation MyViewController

double timerInterval = 1.0f;

- (NSTimer *) timer {
    if (!_timer) {
        _timer = [NSTimer timerWithTimeInterval:timerInterval target:self selector:@selector(onTick:) userInfo:nil repeats:YES];
    }
    return _timer;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

-(void)onTick:(NSTimer*)timer
{
    NSLog(@"Tick...");
}

@end

In qualche modo crea un ciclo di mantenimento, quindi MyViewControllernon viene mai deallocato.
Darrarski,

5
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];

-(void)timerCalled
{
     NSLog(@"Timer Called");
     // Your Code
}

dove hai scritto questo?
Mohit,

1
@JigneshB questa risposta riguarda solo l'uso di NSTimer e non l'utilizzo in background
Mohit

ho scritto con il metodo in background, ovvero - (void) applicationDidEnterBackground: (UIApplication *) application {}
Jignesh B,

con modalità ripetuta SÌ
Jignesh B,

La documentazione di Apple è molto specifica sulla firma del metodo di callback. Il tuo è sbagliato.
Nikolai Ruhe,

2

Le risposte mancano di un orario specifico del giorno qui è l'ora successiva:

NSCalendarUnit allUnits = NSCalendarUnitYear   | NSCalendarUnitMonth |
                          NSCalendarUnitDay    | NSCalendarUnitHour  |
                          NSCalendarUnitMinute | NSCalendarUnitSecond;

NSCalendar *calendar = [[ NSCalendar alloc]  
                          initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *weekdayComponents = [calendar components: allUnits 
                                                  fromDate: [ NSDate date ] ];

[ weekdayComponents setHour: weekdayComponents.hour + 1 ];
[ weekdayComponents setMinute: 0 ];
[ weekdayComponents setSecond: 0 ];

NSDate *nextTime = [ calendar dateFromComponents: weekdayComponents ];

refreshTimer = [[ NSTimer alloc ] initWithFireDate: nextTime
                                          interval: 0.0
                                            target: self
                                          selector: @selector( doRefresh )
                                          userInfo: nil repeats: NO ];

[[NSRunLoop currentRunLoop] addTimer: refreshTimer forMode: NSDefaultRunLoopMode];

Ovviamente, sostituisci "doRefresh" con il metodo desiderato per la tua classe

provare a creare l'oggetto calendario una volta e rendere allUnits statico per efficienza.

l'aggiunta di un componente all'ora funziona perfettamente, non è necessario un test di mezzanotte ( link )

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.