Antworten:
Zunächst möchte ich Sie auf die Cocoa / CF-Dokumentation aufmerksam machen (die immer eine gute erste Anlaufstelle ist). In den Apple-Dokumenten befindet sich oben in jedem Referenzartikel ein Abschnitt mit dem Namen "Companion Guides", in dem Anleitungen für das zu dokumentierende Thema aufgeführt sind (falls vorhanden). Zum Beispiel mit NSTimer
, die Dokumentation listet zwei Begleiter Führungen:
Für Ihre Situation ist der Artikel über Timer-Programmierthemen wahrscheinlich am nützlichsten, während Threading-Themen verwandt sind, jedoch nicht direkt mit der zu dokumentierenden Klasse. Wenn Sie sich den Artikel über Timer-Programmierthemen ansehen, ist er in zwei Teile unterteilt:
Für Artikel, die dieses Format annehmen, gibt es häufig eine Übersicht über die Klasse und deren Verwendung sowie einen Beispielcode für deren Verwendung, in diesem Fall im Abschnitt "Verwenden von Timern". Es gibt Abschnitte zu "Erstellen und Planen eines Timers", "Stoppen eines Timers" und "Speicherverwaltung". Aus dem Artikel geht hervor, dass ein geplanter, sich nicht wiederholender Timer wie folgt erstellt werden kann:
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:@selector(targetMethod:)
userInfo:nil
repeats:NO];
Dadurch wird ein Timer erstellen , die nach 2,0 Sekunden abgefeuert wird , und fordert targetMethod:
auf self
mit einem Argument, das ein Zeiger auf die ist NSTimer
Instanz.
Wenn Sie sich die Methode dann genauer ansehen möchten, können Sie auf die Dokumente zurückgreifen, um weitere Informationen zu erhalten. Es gibt jedoch auch Erklärungen zum Code.
Wenn Sie einen sich wiederholenden Timer stoppen möchten (oder einen sich nicht wiederholenden Timer stoppen möchten, bevor er ausgelöst wird), müssen Sie einen Zeiger auf die erstellte NSTimer
Instanz behalten . Oft muss dies eine Instanzvariable sein, damit Sie in einer anderen Methode darauf verweisen können. Sie können dann invalidate
die NSTimer
Instanz aufrufen :
[myTimer invalidate];
myTimer = nil;
Es wird auch empfohlen nil
, die Instanzvariable zu löschen (wenn beispielsweise Ihre Methode, die den Timer ungültig macht, mehrmals aufgerufen wird und die Instanzvariable nicht auf gesetzt nil
und die NSTimer
Instanz freigegeben wurde, wird eine Ausnahme ausgelöst).
Beachten Sie auch den Punkt zur Speicherverwaltung am Ende des Artikels:
Da die Ausführungsschleife den Timer verwaltet, ist es aus Sicht der Speicherverwaltung normalerweise nicht erforderlich, einen Verweis auf einen Timer zu behalten, nachdem Sie ihn geplant haben . Da der Timer als Argument übergeben wird, wenn Sie seine Methode als Selektor angeben, können Sie einen sich wiederholenden Timer gegebenenfalls innerhalb dieser Methode ungültig machen . In vielen Situationen möchten Sie jedoch auch die Option, den Timer ungültig zu machen - möglicherweise sogar noch vor dem Start. In diesem Fall müssen Sie einen Verweis auf den Timer behalten, damit Sie ihm bei Bedarf eine ungültige Nachricht senden können. Wenn Sie einen außerplanmäßigen Timer erstellen (siehe „Außerplanmäßige Timer“), müssen Sie einen starken Verweis auf den Timer beibehalten (in einer Umgebung mit Referenzzählung behalten Sie ihn bei), damit er nicht freigegeben wird, bevor Sie ihn verwenden.
YES
für , repeats:
wenn Sie anrufen scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
. Wenn Sie dies tun, stellen Sie sicher, dass Sie einen Verweis auf die NSTimer
Instanz behalten (dieser wird von der Methode zurückgegeben), und befolgen Sie den oben beschriebenen Punkt zur Speicherverwaltung.
target
und angeben selector
. Wenn sich beispielsweise Ihr Ziel self
und der Selektor befinden timerMethod:
, wird die Methode timerMethod:
definiert , die beim Auslösen des Timers aufgerufen wird self
. Sie können dann den gewünschten Code in diese Methode einfügen, und die Methode wird immer dann aufgerufen, wenn der Timer ausgelöst wird. Beachten Sie, dass die beim Auslösen des Timers aufgerufene Methode (die Sie als übergeben selector:
) nur ein Argument annehmen kann (das beim Aufrufen ein Zeiger auf die NSTimer
Instanz ist).
self
"
Es gibt verschiedene Möglichkeiten, einen Timer zu verwenden:
1) Geplanter Timer & mit Selektor
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
target: self
selector:@selector(onTick:)
userInfo: nil repeats:NO];
Als Randnotiz können Sie anstelle eines Timers, der sich nicht wiederholt und den Selektor nach einem bestimmten Intervall aufruft, eine einfache Anweisung wie die folgende verwenden:
[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];
Dies hat den gleichen Effekt wie der obige Beispielcode. Wenn Sie den Selektor jedoch jedes n-te Mal aufrufen möchten, verwenden Sie den Timer mit Wiederholungen: YES;
2) selbst geplanter Timer
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];
3) außerplanmäßiger Timer & Aufruf
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];
und danach starten Sie den Timer manuell, wann immer Sie dies benötigen:
NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer: t forMode: NSDefaultRunLoopMode];
Und als Hinweis sieht die onTick: -Methode folgendermaßen aus:
-(void)onTick:(NSTimer *)timer {
//do smth
}
Etwas wie das:
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
target: self
selector: @selector(handleTimer:)
userInfo: nil
repeats: YES];
#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
MyViewController
nie freigegeben wird.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];
-(void)timerCalled
{
NSLog(@"Timer Called");
// Your Code
}
Den Antworten fehlt eine bestimmte Tageszeit. Hier ist die nächste Stunde:
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];
Ersetzen Sie "doRefresh" natürlich durch die gewünschte Methode Ihrer Klasse
Versuchen Sie, das Kalenderobjekt einmal zu erstellen und die allUnits aus Effizienzgründen statisch zu machen.
Das Hinzufügen einer Stunde zur Komponente funktioniert einwandfrei, es ist kein Mitternachtstest erforderlich ( Link )