1

アプリの実行中にユーザーが時計を進めているかどうかを検出しようとしています。私は現在、2 つのタイマーの変化を比較することでこれを行っています:[NSDate timeIntervalSinceReferenceDate]と mach_absolute_time。

基本的なアルゴリズムは次のとおりです。

  • アプリの開始時に、startUserClock (timeIntervalSinceReferenceDate) と startSystemClock (秒に変換された mach_absolute_time) を保存します。
  • タイマーの現在の値をそれぞれの開始値と定期的に比較します。
  • 差分が異なる場合 (多少の誤差の範囲内)、タイマーが同期していないことを知る必要があります。これは、時計の変更を示しています。理論的には、これが可能なのは、ユーザーが時計を変更した場合のみです。

ただし、mach_absolute_time は timeIntervalSinceReferenceDate よりもわずかに速い速度で成長しているようです。短期的には、これは大きな問題ではありませんが、時間の経過とともに差が大きくなり、多くの誤検出が見られるようになります.

この問題は、ハードウェアに依存しているようです。私が持っている iPad 1 ではまったく表示されませんが、同僚の iPad 2 で表示され、シミュレーターで表示されます。

mach_absolute_time を CACurrentMediaTime (内部で mach_absolute_time を使用) に置き換えることで、mach_absolute_time を秒に変換しても問題がないことを確認しました。timeIntervalSinceReferenceDate を他のタイミング メソッド (つまり、CFAbsoluteTimeGetCurrent) に変更しようとしました。

タイマーが同じ速度で成長するという私の基本的な仮定に何か問題がありますか? 私の考えでは、何かが根本的に間違っていない限り、同期がそれほどずれてはならないということでした。両者は時間を決定しているだけであり、異なる点から始まっているだけです。

これを行うより良い方法はありますか?完全にオフラインのソリューションが必要です。インターネット接続は想定できません。

4

2 に答える 2

0

gettimeofdayを使用して、現在のシステム時刻の値を取得してみてください。これは、エポックからの時間を返します。

于 2011-10-17T21:06:38.123 に答える
0

一般に、タイマーは同期しているとは限りません。おそらく、それらは異なるソースから派生したものです。おそらく、1 つがタイム サーバーに対して同期されます。

時間の経過に伴う大きなドリフトではなく、クロック間の差の突然の変化のみを気にします。したがって、クロック間の差の変化率を計算します。

T_Diff := initial difference between clocks
T_Time := time as determined by one clock
Repeat forever:
  T_Diff' := new difference between clocks
  T_Time' := new time as determined by one clock

  # Check if time changed
  if abs((T_Diff'-T_Diff)/(T_Time'-T_Time)) > threshold:
    time_changed()

  # Update state
  T_Diff := T_Diff'
  T_Time := T_Time'

  wait_for_next_update()
于 2011-10-17T21:15:08.180 に答える