Ответы:
Во-первых, я хотел бы обратить ваше внимание на документацию по Какао / CF (которая всегда является отличным первым портом захода). Документы Apple имеют раздел в верхней части каждой справочной статьи под названием «Сопутствующие руководства», в котором перечислены руководства по задокументированной теме (если таковые имеются). Например, с NSTimer
, в документации списки двух гидов - компаньонов:
В вашей ситуации статья «Темы программирования таймера», вероятно, будет самой полезной, хотя темы с потоками связаны, но не имеют непосредственного отношения к документируемому классу. Если вы посмотрите на статью «Темы программирования таймера», она разделена на две части:
Для статей, использующих этот формат, часто есть обзор класса и того, для чего он используется, а затем пример кода, как его использовать, в данном случае в разделе «Использование таймеров». Существуют разделы «Создание и планирование таймера», «Остановка таймера» и «Управление памятью». Из этой статьи создание запланированного неповторяющегося таймера можно сделать примерно так:
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:@selector(targetMethod:)
userInfo:nil
repeats:NO];
Это позволит создать таймер , который запускаемый после 2,0 секунд и вызывает targetMethod:
на self
с одним аргументом, который является указателем на NSTimer
экземпляр.
Если затем вы хотите более подробно взглянуть на метод, вы можете обратиться к документации для получения дополнительной информации, но есть и объяснения вокруг кода.
Если вы хотите остановить повторяющийся таймер (или остановить неповторяющийся таймер до его запуска), вам необходимо сохранить указатель на NSTimer
созданный экземпляр; часто это должна быть переменная экземпляра, чтобы вы могли ссылаться на нее в другом методе. После этого вы можете позвонить invalidate
по NSTimer
примеру:
[myTimer invalidate];
myTimer = nil;
Также хорошей практикой является nil
исключение переменной экземпляра (например, если ваш метод, который делает недействительным таймер, вызывается более одного раза, а переменная экземпляра не была установлена в значение nil
и NSTimer
экземпляр был освобожден, он вызовет исключение).
Обратите также внимание на пункт «Управление памятью» в нижней части статьи:
Поскольку цикл выполнения поддерживает таймер, с точки зрения управления памятью обычно нет необходимости сохранять ссылку на таймер после того, как вы запланировали его . Так как таймер передается в качестве аргумента , когда вы укажете свой метод как селектор, . Если вы создаете незапланированный таймер (см. «Незапланированные таймеры»), то вы должны поддерживать надежную ссылку на таймер (в среде с подсчетом ссылок вы сохраняете его), чтобы он не был освобожден перед его использованием. вы можете сделать недействительным повторяющийся таймер, когда это уместно в этом методе . Однако во многих ситуациях вы также хотите отключить таймер - возможно, даже до его запуска. В этом случае вам нужно сохранить ссылку на таймер, чтобы вы могли отправлять ему сообщение о недействительности в случае необходимости.
YES
для repeats:
когда вы звоните scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
. Если вы сделаете это, убедитесь, что сохранили ссылку на NSTimer
экземпляр (он возвращается методом) и следуйте пункту «Управление памятью», как я подробно описал выше.
target
и selector
. Например, если ваша цель self
и селектор timerMethod:
, метод, вызываемый при срабатывании таймера, timerMethod:
определяется в self
. Затем вы можете поместить любой код в этот метод, и метод будет вызываться всякий раз, когда срабатывает таймер. Обратите внимание, что метод, вызываемый при срабатывании таймера (который вы передаете как selector:
), может принимать только один аргумент (который при вызове является указателем на NSTimer
экземпляр).
self
"
Есть несколько способов использования таймера:
1) запланированный таймер и использование селектора
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
target: self
selector:@selector(onTick:)
userInfo: nil repeats:NO];
В качестве примечания, вместо использования таймера, который не повторяется и вызывает селектор после определенного интервала, вы можете использовать простое утверждение, подобное этому:
[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];
это будет иметь тот же эффект, что и пример кода выше; но если вы хотите вызывать селектор каждый раз, вы используете таймер с повторениями: YES;
2) таймер
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) незапланированный таймер и использование вызова
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];
и после этого вы запускаете таймер вручную всякий раз, когда вам нужно:
NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer: t forMode: NSDefaultRunLoopMode];
И как примечание, метод onTick: выглядит следующим образом:
-(void)onTick:(NSTimer *)timer {
//do smth
}
Что-то вроде этого:
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
никогда не освобождается.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];
-(void)timerCalled
{
NSLog(@"Timer Called");
// Your Code
}
В ответах отсутствует конкретное время, таймер дня здесь на следующий час:
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];
Конечно, замените «doRefresh» желаемым методом вашего класса
попытайтесь создать объект календаря один раз и сделайте allUnits статическим для эффективности.
добавление одного к часу компонента работает просто отлично, нет необходимости в полуночном тесте ( ссылка )