Cum se utilizează NSTimer? (Programare, Obiectiv C, Cacao, Nstimer)

lab12 a intrebat.

Cum se utilizează un NSTimer? Poate cineva să-mi dea instrucțiuni pas cu pas?

Comentarii

6 răspunsuri
Alex Rozanski

În primul rând, aș vrea să vă atrag atenția asupra documentației Cocoa/CF (care este întotdeauna un excelent prim punct de apel). Documentația Apple are o secțiune în partea de sus a fiecărui articol de referință numită „Companion Guides”, care enumeră ghidurile pentru subiectul documentat (dacă există). De exemplu, cu NSTimer, documentația enumeră două ghiduri însoțitoare:

Pentru situația dvs., articolul Timer Programming Topics este probabil cel mai util, în timp ce subiectele legate de threading sunt conexe, dar nu sunt cele mai direct legate de clasa care este documentată. Dacă aruncați o privire la articolul Timer Programming Topics, acesta este împărțit în două părți:

  • Cronometre
  • Utilizarea temporizatoarelor

Pentru articolele care au acest format, există adesea o prezentare generală a clasei și a scopului pentru care este utilizată, iar apoi câteva exemple de cod pe modul în care pentru a o utiliza, în acest caz în secțiunea „Using Timers”. Există secțiuni privind „Crearea și programarea unui cronometru”, „Oprirea unui cronometru” și „Gestionarea memoriei”. Din articol, crearea unui temporizator programat, care nu se repetă, se poate face cam așa:

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

Acest lucru va crea un temporizator care este declanșat după 2,0 secunde și care apelează targetMethod: pe self cu un singur argument, care este un pointer la fișierul NSTimer instanță.

Dacă doriți apoi să analizați mai în detaliu metoda, puteți consulta documentația pentru mai multe informații, dar există și explicații în jurul codului.

Dacă doriți să opriți un cronometru care se repetă (sau să opriți un cronometru care nu se repetă înainte de a se declanșa), atunci trebuie să păstrați un pointer la instanța NSTimer instanță care a fost creată; deseori, aceasta va trebui să fie o variabilă de instanță, astfel încât să puteți face referire la ea într-o altă metodă. Apoi puteți apela invalidate asupra clasei NSTimer instanță:

[myTimer invalidate];
myTimer = nil;

De asemenea, este o bună practică să nil de exemplu, dacă metoda care invalidează cronometrul este apelată de mai multe ori și dacă variabila de instanță nu a fost setată la nil iar metoda NSTimer instanța a fost dezalocată, se va arunca o excepție).

Rețineți, de asemenea, punctul privind gestionarea memoriei din partea de jos a articolului:

Deoarece bucla de execuție menține cronometrul, din perspectiva gestionării memoriei de obicei nu este nevoie să păstrați o referință la un temporizator după ce l-ați programat. Deoarece temporizatorul este transmis ca argument atunci când specificați metoda sa ca un selector, puteți invalida un temporizator repetitiv atunci când este cazul în cadrul metodei respective.. Cu toate acestea, în multe situații, doriți, de asemenea, opțiunea de a invalida temporizatorul – poate chiar înainte de a începe. În acest caz, trebuie să păstrați o referință la temporizator, astfel încât să puteți trimite un mesaj de invalidare ori de câte ori este necesar.. Dacă creați un temporizator neprogramat (a se vedea „Temporizatoare neprogramate”), atunci trebuie să păstrați o referință puternică la temporizator (într-un mediu cu numărătoare de referințe, o păstrați), astfel încât acesta să nu fie dezalocat înainte de a-l utiliza.

Comentarii

  • Okk, o întrebare, ce aș putea pune ca și cod care să fie executat la fiecare două secunde? –  > Por lab12.
  • Ai trece YES pentru repeats: atunci când apelați scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:. Dacă faceți acest lucru, atunci asigurați-vă că păstrați o referință la NSTimer instanță (aceasta este returnată de metodă) și urmați punctul privind gestionarea memoriei, așa cum am detaliat mai sus. –  > Por Alex Rozanski.
  • Nu, unde aș putea pune codul care să fie pornit la fiecare 2 secunde? De exemplu, să zicem că aș vrea să facă un bip la fiecare 2 secunde. unde aș pune codul de zgomot de bip…? –  > Por lab12.
  • În metoda pe care ați specificat-o cu ajutorul instrucțiunii target și selector. De exemplu, dacă ținta dumneavoastră este self și selectorul este timerMethod:, metoda apelată atunci când se declanșează temporizatorul este timerMethod: definită pe self. Apoi puteți introduce orice cod doriți în această metodă, iar metoda va fi apelată de fiecare dată când se declanșează temporizatorul. Rețineți că metoda apelată atunci când se declanșează temporizatorul (pe care o treceți ca fiind selector:) nu poate primi decât un singur argument (care, atunci când este apelat, este un pointer către NSTimer instanță). –  > Por Alex Rozanski.
  • Scuze, am vrut să spun „definit pe self” –  > Por Alex Rozanski.
Woofy

există câteva moduri de a folosi un temporizator:

1) temporizator programat & folosind selector

NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
                      target: self
                      selector:@selector(onTick:)
                      userInfo: nil repeats:NO];
  • dacă setați repetarea la NU, temporizatorul va aștepta 2 secunde înainte de a rula selectorul și după aceea se va opri;
  • dacă repeți: DA, temporizatorul va porni imediat și va repeta apelarea selectorului la fiecare 2 secunde;
  • pentru a opri cronometrul, apelați metoda -invalidate a cronometrului: [t invalidate];

Ca o notă secundară, în loc să folosiți un temporizator care nu se repetă și care apelează selectorul după un interval specificat, ați putea folosi o instrucțiune simplă ca aceasta:

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

acest lucru va avea același efect ca și în exemplul de cod de mai sus; dar dacă doriți să apelați selectorul la fiecare a n-a oară, utilizați cronometrul cu repeats:YES;

2) temporizator cu programare proprie

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];
  • acest lucru va crea un temporizator care se va porni singur la o dată personalizată specificată de dvs. (în acest caz, după un minut) și se repetă la fiecare secundă

3) cronometru neprogramat & folosind invocarea

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

iar după aceea, veți porni cronometrul manual ori de câte ori aveți nevoie, astfel:

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

Și ca o notă, metoda onTick: arată astfel::

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

Comentarii

  • Ok, dar vedeți că vreau să scad transparența aplicației mele, așa că nu știu cum să aplic asta cu NSTimer –  > Por lab12.
  • 24

  • Doamne, oamenii ăștia de azi… votează jos de la mine pentru că nu ai specificat asta de la început și lasă-ne să scriem în zadar! –  > Por Woofy.
  • 28

  • Nu ați scris în zadar. Este o informație BUNĂ! –  > Por willc2.
  • În metoda 2, „cronometru autoprogramat”, cum pot opri cronometrul când vreau eu? –  > Por Satyam.
  • @Satyamsvvv, puteți opri cronometrul prin invocarea, să zicem, a unei alte metode având: [timer invalidate]; timer = nil; –  > Por Kimpoy.
ennuikiller

Ceva de genul acesta:

NSTimer *timer;

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

Comentarii

  • Încă mai merge puternic … și în 2014! –  > Por Muruganandham K.
Dan
#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

Comentarii

  • Cumva se creează ciclul de reținere, așa că MyViewController nu este niciodată dezalocat. –  > Por Darrarski.
Mohit
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];

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

Comentarii

  • unde ai scris asta? –  > Por Mohit.
  • @JigneshB acest răspuns este doar despre cum să utilizați NSTimer nu despre utilizarea în fundal –  > Por Mohit.
  • am scris în metoda de fundal, adică -(void)applicationDidEnterBackground:(UIApplication *)application {} – – (void)applicationDidEnterBackground:(UIApplication *)application {}  > Por Jignesh B.
  • cu modul repetat DA –  > Por Jignesh B.
  • Documentația Apple este foarte specifică în ceea ce privește semnătura metodei de apelare. A ta este greșită. –  > Por Nikolai Ruhe.
gjpc

Răspunsurile lipsesc un anumit moment al zilei cronometru aici este pe următoarea oră:

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

Desigur, înlocuiți „doRefresh” cu metoda dorită a clasei dvs.

încercați să creați obiectul calendar o singură dată și să faceți allUnits un static pentru eficiență.

adăugarea unui la componenta de oră funcționează foarte bine, nu este nevoie de un test la miezul nopții (link)