回答:
最初に、Cocoa / CFのドキュメントに注意を向けたいと思います(これは常に最初の呼び出しポートとして優れています)。Appleのドキュメントの各リファレンス記事の上部には、「コンパニオンガイド」と呼ばれるセクションがあり、ドキュメント化されているトピック(存在する場合)のガイドがリストされています。たとえば、のNSTimer
場合、ドキュメントには2つの関連ガイドが記載されています。
スレッドトピックは関連していますが、ドキュメント化されているクラスに最も直接関連しているわけではありませんが、状況によっては、タイマープログラミングトピックの記事が最も役立つでしょう。タイマープログラミングトピックの記事を見ると、2つのパートに分かれています。
この形式の記事では、多くの場合、クラスとその使用目的の概要があり、次に、この場合の「タイマーの使用」セクションにある、その使用方法に関するサンプルコードがあります。「タイマーの作成とスケジューリング」、「タイマーの停止」、「メモリー管理」のセクションがあります。記事から、スケジュールされた非繰り返しタイマーを作成するには、次のようにします。
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:@selector(targetMethod:)
userInfo:nil
repeats:NO];
これにより、2.0秒後に起動され、インスタンスへのポインタである1つの引数で呼び出されるタイマーが作成さ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:
)は、1つの引数(呼び出されたときに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回ごとに呼び出す場合は、タイマーをrepeats: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を静的にしてみてください。
1時間のコンポーネントを追加しても問題なく動作し、午前0時のテストは必要ありません(リンク)