#objective-c #ios #nsdate #clock #anti-cheat
#objective-c #iOS #nsdate #часы #античит
Вопрос:
Я пытаюсь определить, продвигает ли пользователь свои часы во время работы приложения. В настоящее время я делаю это, сравнивая, как меняются два таймера: [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 под капотом). Я попытался изменить timeIntervalSinceReferenceDate на другие методы синхронизации (например: CFAbsoluteTimeGetCurrent).
Что-то не так с моим базовым предположением о том, что таймеры должны расти с одинаковой скоростью? Я думал, что, если что-то в корне не так, они не должны так рассинхронизироваться — они оба определяют время, просто начиная с разных точек.
Есть ли лучший способ сделать это? Мне нужно полностью автономное решение — мы не можем предположить подключение к Интернету.
Комментарии:
1. не уверен, но меняется ли время на телефоне при смене часовых поясов?
Ответ №1:
Вы можете попробовать использовать gettimeofday, чтобы получить значение текущего системного времени. Это возвращает время с момента начала эпохи.
Ответ №2:
В общем, синхронизация таймеров не гарантируется. Возможно, они получены из разных источников. Возможно, один из них синхронизирован с сервером времени.
Вас интересуют только внезапные изменения в разнице между часами, а не большие отклонения во времени. Итак, вычислите скорость изменения разницы между часами:
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()
Комментарии:
1. К сожалению, эта схема не совсем работает — если пользователь переводит приложение в фоновый режим на длительное время (что очень возможно при многозадачности), при возврате дрейф может быть достаточно большим, чтобы вызвать ложное срабатывание. В нашем случае ложные срабатывания довольно дорогостоящие.
2. Вот почему схема рассматривает дрейф с течением времени, а не сам дрейф. Хотя это не показано выше, вы, вероятно, захотите установить нижний предел времени между обновлениями состояния, чтобы можно было точно вычислить это.