Получение времени, прошедшего в Objective-C

Мне нужно получить время, прошедшее между двумя событиями, например, появление UIView и первой реакции пользователя.

Как я могу достичь этого в Objective-C?

Ответ 1

NSDate *start = [NSDate date];
// do stuff...
NSTimeInterval timeInterval = [start timeIntervalSinceNow];

timeInterval - разница между началом и теперь, в секундах, с точностью до миллисекунды.

Ответ 2

Вы не должны полагаться на [NSDate date] в целях определения времени, так как он может over- или занижать прошедшее время. Есть даже случаи, когда ваш компьютер будет путешествовать во времени, так как прошедшее время будет отрицательным! (Например, если часы переместились назад во время.)

Согласно Арии Хагиги в лекции "Расширенное распознавание жестов iOS" курса iOS 2013 года в Стэнфорде (34:00), вам следует использовать CACurrentMediaTime() если вам нужен точный интервал времени.

Objective-C:

#import <QuartzCore/QuartzCore.h>
CFTimeInterval startTime = CACurrentMediaTime();
// perform some action
CFTimeInterval elapsedTime = CACurrentMediaTime() - startTime;

Swift:

let startTime = CACurrentMediaTime()
// perform some action
let elapsedTime = CACurrentMediaTime() - startTime

Причина в том, что [NSDate date] синхронизируется на сервере, поэтому это может привести к " [NSDate date] синхронизации по времени", что может привести к очень трудным для отслеживания ошибкам. CACurrentMediaTime(), с другой стороны, это время устройства, которое не изменяется с этими сетевыми синхронизациями.

Вам нужно будет добавить платформу QuartzCore в ваши целевые настройки.

Ответ 3

Использовать метод timeIntervalSinceDate

NSTimeInterval secondsElapsed = [secondDate timeIntervalSinceDate:firstDate];

NSTimeInterval является просто a double, определите в NSDate следующим образом:

typedef double NSTimeInterval;

Ответ 4

Для тех, кто приезжает сюда в поисках реализации getTickCount() для iOS, вот мое после объединения различных источников.

Ранее у меня была ошибка в этом коде (сначала я разделил на 1000000), которая приводила к некоторому количественному определению выходных данных на моем iPhone 6 (возможно, это не было проблемой на iPhone 4/etc или я просто никогда этого не замечал). Обратите внимание, что если сначала не выполнить это деление, существует некоторый риск переполнения, если числитель временной базы достаточно велик. Если кому-то интересно, здесь есть ссылка с гораздо более подробной информацией: fooobar.com/questions/9807/...

В свете этой информации, возможно, безопаснее использовать функцию Apple CACurrentMediaTime !

Я также mach_timebase_info вызов 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. на моем 125/3 6 было 125/3.

Решение с использованием CACurrentMediaTime() довольно тривиально:

uint64_t getTickCount(void)
{
    double ret = CACurrentMediaTime();
    return ret * 1000;
}

Ответ 6

используйте функцию timeIntervalSince1970 класса NSDate, как показано ниже:

double start = [startDate timeIntervalSince1970];
double end = [endDate timeIntervalSince1970];
double difference = end - start;

в основном это то, что я использую, чтобы сравнить разницу в секундах между двумя разными датами. также проверьте эту ссылку здесь

Ответ 7

Другие ответы правильны (с оговоркой *). Я добавляю этот ответ просто, чтобы показать пример использования:

- (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 для вычисления прошедшего времени только для случайных целей. Одной из таких целей может быть обычное тестирование, сырое профилирование, где вам просто нужно грубое представление о том, как долго проходит метод.

Риск состоит в том, что установка времени текущего времени устройства устройства может измениться в любой момент из-за синхронизации сетевых часов. Таким NSDate время NSDate может двигаться вперед или назад в любой момент.