たとえば、UIViewの外観とユーザーの最初の反応など、2つのイベント間の経過時間を取得する必要があります。
Objective-Cでそれを実現するにはどうすればよいですか?
たとえば、UIViewの外観とユーザーの最初の反応など、2つのイベント間の経過時間を取得する必要があります。
Objective-Cでそれを実現するにはどうすればよいですか?
回答:
NSDate *start = [NSDate date];
// do stuff...
NSTimeInterval timeInterval = [start timeIntervalSinceNow];
timeInterval
ミリ秒単位の精度での秒単位の開始と現在の差です。
[NSDate date]
経過時間を過大または過小報告する可能性があるため、タイミングの目的に依存しないでください。経過時間がマイナスになるので、コンピュータがタイムトラベルのように見える場合さえあります!(たとえば、タイミング中にクロックが逆方向に移動した場合)。
2013年冬のStanford iOSコース(34:00)の「高度なiOSジェスチャー認識」講義のAria HaghighiによるとCACurrentMediaTime()
、正確な時間間隔が必要な場合は、これを使用する必要があります。
Objective-C:
#import <QuartzCore/QuartzCore.h>
CFTimeInterval startTime = CACurrentMediaTime();
// perform some action
CFTimeInterval elapsedTime = CACurrentMediaTime() - startTime;
迅速:
let startTime = CACurrentMediaTime()
// perform some action
let elapsedTime = CACurrentMediaTime() - startTime
その理由は[NSDate date]
、サーバー上で同期するため、「時間同期の問題」につながり、追跡が非常に困難なバグにつながる可能性があるためです。CACurrentMediaTime()
一方、は、これらのネットワーク同期で変化しないデバイス時間です。
あなたはする必要があります追加QuartzCoreフレームワークをターゲットの設定に。
[NSDate date]
ディスパッチブロック内の完了ブロック内で呼び出すと、[NSDate date]
実行が私のブロックが作成されたポイントに到達する直前に報告されていたのと同じ「現在の」時間を取得していました。CACurrentMediaTime()
この問題を解決しました。
CACurrentMediaTime()
デバイスがスリープ状態になると、がカチカチと止まることに注意してください。デバイスをコンピューターから切断してテストする場合は、ロックしてから10分ほど待つと、実CACurrentMediaTime()
時間に追いつかないことがわかります。
ここに来てiOSのgetTickCount()実装を探している人のために、さまざまなソースをまとめた後のものがここにあります。
以前、私はこのコードにバグがあり(最初に1000000で割った)、iPhone 6で出力の量子化を引き起こしていました(おそらく、これはiPhone 4 / etcでは問題ではなかったか、気づかなかっただけです)。最初にその除算を実行しないと、タイムベースの分子が非常に大きい場合にオーバーフローが発生するリスクがあることに注意してください。誰かが好奇心を持っている場合は、ここに詳細についてのリンクがあります:https : //stackoverflow.com/a/23378064/588476
その情報に照らして、Appleの機能を使用する方が安全かもしれませんCACurrentMediaTime
。
また、mach_timebase_info
呼び出しのベンチマークを行ったところ、iPhone 6で約19ナノ秒かかるため、その呼び出しの出力をキャッシュしていた(スレッドセーフではない)コードを削除しました。
#include <mach/mach.h>
#include <mach/mach_time.h>
uint64_t getTickCount(void)
{
mach_timebase_info_data_t sTimebaseInfo;
uint64_t machTime = mach_absolute_time();
// Convert to milliseconds
mach_timebase_info(&sTimebaseInfo);
machTime *= sTimebaseInfo.numer;
machTime /= sTimebaseInfo.denom;
machTime /= 1000000; // convert from nanoseconds to milliseconds
return machTime;
}
タイムベースコールの出力によっては、オーバーフローの潜在的なリスクに注意してください。私はそれがiPhoneのモデルごとに一定であるかもしれないと思います(しかし、わかりません)。私のiPhone 6でそれはだった125/3
。
使用するソリューションCACurrentMediaTime()
は非常に簡単です:
uint64_t getTickCount(void)
{
double ret = CACurrentMediaTime();
return ret * 1000;
}
mach_timebase_info()
渡されmach_timebase_info_data_t
た{0,0}
値を実際の値に設定する前ににリセットします。これにより、コードが複数のスレッドから呼び出された場合にゼロ除算が発生する可能性があります。dispatch_once()
代わりに使用してください(またはCACurrentMediaTime
単にマッハ時間が秒に変換されます)。
:(のGetTickCountのような)percise時間測定のために、またmach_absolute_timeを見て、このAppleのQ&A取るhttp://developer.apple.com/qa/qa2004/qa1398.htmlを。
他の答えは正解です(警告*付き)。この回答を追加して、使用例を示します。
- (void)getYourAffairsInOrder
{
NSDate* methodStart = [NSDate date]; // Capture start time.
// … Do some work …
NSLog(@"DEBUG Method %s ran. Elapsed: %f seconds.", __func__, -([methodStart timeIntervalSinceNow])); // Calculate and report elapsed time.
}
デバッガーコンソールに、次のようなものが表示されます。
DEBUG Method '-[XMAppDelegate getYourAffairsInOrder]' ran. Elapsed: 0.033827 seconds.
*注意:他の人が述べたように、NSDate
カジュアルな目的でのみ経過時間を計算するために使用します。そのような目的の1つは、一般的なテスト、大まかなプロファイリングであり、メソッドの所要時間のおおよその目安が必要な場合があります。
ネットワーククロックの同期により、デバイスのクロックの現在の時刻設定がいつでも変更される可能性があります。したがって、NSDate
時間はいつでも前後にジャンプする可能性があります。
fabs(...)
floatの絶対値を取得するために使用できる@NicolasZozol 。例えば。NSTimeInterval timeInterval = fabs([start timeIntervalSinceNow]);