[iphone] Objective-C에서 예를 들어 밀리 초 단위로 정확한 시간을 어떻게 얻을 수 있습니까?

매우 정확하게 시간을 얻는 쉬운 방법이 있습니까?

메서드 호출 간의 지연을 계산해야합니다. 보다 구체적으로 UIScrollView에서 스크롤 속도를 계산하고 싶습니다.



답변

NSDate그리고 timeIntervalSince*메소드는 반환 NSTimeInterval밀리 초 이하의 정확도로 이중 인을. NSTimeInterval초 단위이지만 더 큰 정밀도를 제공하기 위해 double을 사용합니다.

밀리 초 시간 정확도를 계산하기 위해 다음을 수행 할 수 있습니다.

// Get a current time for where you want to start measuring from
NSDate *date = [NSDate date];

// do work...

// Find elapsed time and convert to milliseconds
// Use (-) modifier to conversion since receiver is earlier than now
double timePassed_ms = [date timeIntervalSinceNow] * -1000.0;

timeIntervalSinceNow에 대한 문서 .

을 사용하여이 간격을 계산하는 다른 많은 방법이 있으며 NSDate Class ReferenceNSDate 에있는 클래스 문서를 참조 NSDate하는 것이 좋습니다 .


답변

mach_absolute_time() 정확한 측정을 위해 사용할 수 있습니다.

참조 http://developer.apple.com/qa/qa2004/qa1398.html를

또한 볼 수 있습니다 CACurrentMediaTime()본질적으로 같은 일을하지만, 사용하기 쉬운 인터페이스이다.

(참고 :이 답변은 2009 년에 작성되었습니다. clock_gettime()최신 버전의 macOS 및 iOS에서 사용할 수있는 더 간단한 POSIX 인터페이스에 대한 Pavel Alexeev의 답변을 참조하십시오 .)


답변

사용하지 마십시오 NSDate, CFAbsoluteTimeGetCurrent또는 gettimeofday경과 시간을 측정 할 수 있습니다. 이들은 모두 시스템 시계에 의존하며, 이는 네트워크 시간 동기화 (NTP) 시계 업데이트 (드리프트를 조정하기 위해 자주 발생 함), DST 조정, 윤초 등과 같은 다양한 이유로 인해 언제든지 변경 될 수 있습니다 .

즉, 다운로드 또는 업로드 속도를 측정하는 경우 실제로 발생한 일과 관련이없는 수치가 갑자기 급증하거나 감소하게됩니다. 성능 테스트에는 이상하게 잘못된 이상 값이 있습니다. 잘못된 기간이 지나면 수동 타이머가 트리거됩니다. 시간은 뒤로 갈 수도 있고 음의 델타로 끝날 수 있으며 무한 재귀 또는 데드 코드로 끝날 수 있습니다 (예,이 두 가지를 모두 수행했습니다).

사용 mach_absolute_time. 커널이 부팅 된 이후의 실제 시간을 측정합니다. 단조롭게 증가하며 (뒤로 이동하지 않음) 날짜 및 시간 설정의 영향을받지 않습니다. 작업하는 것이 고통스럽기 때문에 다음을 제공하는 간단한 래퍼가 있습니다 NSTimeInterval.

// LBClock.h
@interface LBClock : NSObject
+ (instancetype)sharedClock;
// since device boot or something. Monotonically increasing, unaffected by date and time settings
- (NSTimeInterval)absoluteTime;

- (NSTimeInterval)machAbsoluteToTimeInterval:(uint64_t)machAbsolute;
@end

// LBClock.m
#include <mach/mach.h>
#include <mach/mach_time.h>

@implementation LBClock
{
    mach_timebase_info_data_t _clock_timebase;
}

+ (instancetype)sharedClock
{
    static LBClock *g;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        g = [LBClock new];
    });
    return g;
}

- (id)init
{
    if(!(self = [super init]))
        return nil;
    mach_timebase_info(&_clock_timebase);
    return self;
}

- (NSTimeInterval)machAbsoluteToTimeInterval:(uint64_t)machAbsolute
{
    uint64_t nanos = (machAbsolute * _clock_timebase.numer) / _clock_timebase.denom;

    return nanos/1.0e9;
}

- (NSTimeInterval)absoluteTime
{
    uint64_t machtime = mach_absolute_time();
    return [self machAbsoluteToTimeInterval:machtime];
}
@end


답변

CFAbsoluteTimeGetCurrent()A와 절대 시간 반환 double값을,하지만 난 정밀도가 무엇인지 모르는 -이 있습니다 매 수십 밀리 초를 업데이트하거나 모든 마이크로를, 나도 몰라 업데이트 할 수 있습니다.


답변

mach_absolute_time()틱 (아마 가동 시간)을 사용하여 절대 시간 동안 커널과 프로세서의 조합을 쿼리 하기 때문에 사용하지 않을 것입니다.

내가 사용하는 것 :

CFAbsoluteTimeGetCurrent();

이 기능은 iOS 및 OSX 소프트웨어 및 하드웨어의 차이를 수정하도록 최적화되어 있습니다.

더 괴짜

차이의 지수 mach_absolute_time()와는 AFAbsoluteTimeGetCurrent()항상 주위 24000011.154871입니다

다음은 내 앱의 로그입니다.

최종 결과 시간에 차이가 있음을하시기 바랍니다 노트 CFAbsoluteTimeGetCurrent()의이

 2012-03-19 21:46:35.609 Rest Counter[3776:707] First Time: 353900795.609040
 2012-03-19 21:46:36.360 Rest Counter[3776:707] Second Time: 353900796.360177
 2012-03-19 21:46:36.361 Rest Counter[3776:707] Final Result Time (difference): 0.751137
 2012-03-19 21:46:36.363 Rest Counter[3776:707] Mach absolute time: 18027372
 2012-03-19 21:46:36.365 Rest Counter[3776:707] Mach absolute time/final time: 24000113.153295
 2012-03-19 21:46:36.367 Rest Counter[3776:707] -----------------------------------------------------
 2012-03-19 21:46:43.074 Rest Counter[3776:707] First Time: 353900803.074637
 2012-03-19 21:46:43.170 Rest Counter[3776:707] Second Time: 353900803.170256
 2012-03-19 21:46:43.172 Rest Counter[3776:707] Final Result Time (difference): 0.095619
 2012-03-19 21:46:43.173 Rest Counter[3776:707] Mach absolute time: 2294833
 2012-03-19 21:46:43.175 Rest Counter[3776:707] Mach absolute time/final time: 23999753.727777
 2012-03-19 21:46:43.177 Rest Counter[3776:707] -----------------------------------------------------
 2012-03-19 21:46:46.499 Rest Counter[3776:707] First Time: 353900806.499199
 2012-03-19 21:46:55.017 Rest Counter[3776:707] Second Time: 353900815.016985
 2012-03-19 21:46:55.018 Rest Counter[3776:707] Final Result Time (difference): 8.517786
 2012-03-19 21:46:55.020 Rest Counter[3776:707] Mach absolute time: 204426836
 2012-03-19 21:46:55.022 Rest Counter[3776:707] Mach absolute time/final time: 23999996.639500
 2012-03-19 21:46:55.024 Rest Counter[3776:707] -----------------------------------------------------


답변

#define CTTimeStart() NSDate * __date = [NSDate date]
#define CTTimeEnd(MSG) NSLog(MSG " %g",[__date timeIntervalSinceNow]*-1)

용법:

CTTimeStart();
...
CTTimeEnd(@"that was a long time:");

산출:

2013-08-23 15:34:39.558 App-Dev[21229:907] that was a long time: .0023


답변

또한 NSNumberCoreData에 저장하려는 경우 Unix epoch (밀리 초)로 초기화 된 64 비트를 계산하는 방법도 있습니다. 이런 방식으로 날짜를 저장하는 시스템과 상호 작용하는 내 앱에 필요했습니다.

  + (NSNumber*) longUnixEpoch {
      return [NSNumber numberWithLongLong:[[NSDate date] timeIntervalSince1970] * 1000];
  }