Як я можу використовувати NSTimer
? Хтось може дати мені покрокові інструкції?
Як я можу використовувати NSTimer
? Хтось може дати мені покрокові інструкції?
Відповіді:
По-перше, я хотів би звернути вашу увагу на документацію щодо какао / 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];
це матиме такий же ефект, як і зразок коду, наведеного вище; але якщо ви хочете викликати селектор щоразу в n-й раз, ви використовуєте таймер з повторами: ТАК;
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 статичним для ефективності.
додавання одного годинного компонента працює чудово, не потрібно тестування опівночі ( посилання )