どのようにNSTimer
を使うのですか?誰もが私に一歩一歩指示を与えることができますか?
まず、Cocoa/CFのドキュメントに注意を向けたいと思います(これは、常に素晴らしい最初の呼び出しです)。 Appleドキュメントの各リファレンス記事の上部に「Companion Guides」と呼ばれるセクションがあり、ドキュメント化されているトピックのガイド(存在する場合)がリストされています。たとえば、NSTimer
の場合、 ドキュメント には2つのコンパニオンガイドがリストされます。
状況については、タイマープログラミングトピックの記事が最も役立つと思われます。スレッドトピックは関連していますが、文書化されているクラスに最も直接関連しているわけではありません。タイマープログラミングトピックの記事を見ると、2つの部分に分かれています。
この形式をとる記事の場合、クラスの概要とその使用目的がよくあり、次にhowのサンプルコードがあります。この場合は、タイマーの使用」セクション。 「タイマーの作成とスケジューリング」、「タイマーの停止」、「メモリ管理」のセクションがあります。この記事から、スケジュールされた非繰り返しタイマーの作成は次のようにできます。
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:@selector(targetMethod:)
userInfo:nil
repeats:NO];
これにより、2.0秒後に起動されるタイマーが作成され、self
インスタンスへのポインターである1つの引数を使用して、NSTimer
でtargetMethod:
が呼び出されます。
その後、メソッドをさらに詳しく調べたい場合は、ドキュメントを参照して詳細を確認できますが、コードに関する説明もあります。
繰り返されるタイマーを停止する場合(または、起動する前に非繰り返しタイマーを停止する場合)、作成されたNSTimer
インスタンスへのポインターを保持する必要があります。多くの場合、これは別のメソッドで参照できるようにインスタンス変数である必要があります。その後、invalidate
インスタンスでNSTimer
を呼び出すことができます。
[myTimer invalidate];
myTimer = nil;
インスタンス変数をnil
アウトすることもお勧めです(たとえば、タイマーを無効にするメソッドが複数回呼び出され、インスタンス変数がnil
に設定されておらず、NSTimer
インスタンスが割り当て解除された場合、例外をスローします) 。
また、記事の下部にあるメモリ管理のポイントにも注意してください。
実行ループはタイマーを維持するため、メモリ管理の観点から、通常、スケジュールした後にタイマーへの参照を保持する必要はありません。メソッドとしてセレクターを指定すると、タイマーが引数として渡されるため、そのメソッド内で適切な場合に繰り返しタイマーを無効にできます。ただし、多くの状況では、タイマーを無効にするオプションも必要です。おそらく、タイマーが開始する前であってもです。 この場合、タイマーへの参照を保持する必要があるため、適切なときに無効化メッセージを送信できます。スケジュールされていないタイマー(「スケジュールされていないタイマー」を参照)を作成する場合、使用する前に割り当てが解除されないように、タイマーへの強い参照を保持する必要があります(参照カウント環境で保持します)。
タイマーを使用する方法はいくつかあります。
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];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];
-(void)timerCalled
{
NSLog(@"Timer Called");
// Your Code
}
#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
答えはここに次の時間にある特定の時刻タイマーが抜けています:
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を効率的にするためにstaticにします。
時間コンポーネントに1を追加することはちょうどうまく働きます、真夜中テストの必要はありません( link )