Existe uma maneira fácil de obter uma hora com muita precisão?
Preciso calcular alguns atrasos entre chamadas de método. Mais especificamente, desejo calcular a velocidade de rolagem em um UIScrollView.
iphone
objective-c
cocoa-touch
uikit
obrigado
fonte
fonte
Respostas:
NSDate
e ostimeIntervalSince*
métodos retornarão aNSTimeInterval
que é um double com precisão de submilissegundos.NSTimeInterval
é em segundos, mas usa o dobro para dar a você maior precisão.Para calcular a precisão do tempo em milissegundos, você pode fazer:
Documentação em timeIntervalSinceNow .
Existem muitas outras maneiras de calcular esse intervalo usando
NSDate
, e eu recomendaria olhar a documentação da classeNSDate
encontrada em Referência de classe NSDate .fonte
NSDate
emach_absolute_time()
em cerca de 30ms de nível. 27 vs. 29, 36 vs. 39, 43 vs. 45.NSDate
foi mais fácil de usar para mim e os resultados foram semelhantes o suficiente para não me importar.mach_absolute_time()
pode ser usado para obter medições precisas.Veja http://developer.apple.com/qa/qa2004/qa1398.html
Também está disponível
CACurrentMediaTime()
, que é essencialmente a mesma coisa, mas com uma interface mais fácil de usar.(Observação: essa resposta foi escrita em 2009. Consulte a resposta de Pavel Alexeev para as
clock_gettime()
interfaces POSIX mais simples disponíveis nas versões mais recentes do macOS e iOS.)fonte
CACurrentMediaTime()
que convertemach_absolute_time()
diretamente em umdouble
.elapsedNano
é do tipoNanoseconds
, que não é um tipo inteiro simples. É um alias deUnsignedWide
, que é uma estrutura com dois campos inteiros de 32 bits. Você pode usar emUnsignedWideToUInt64()
vez do elenco, se preferir.Por favor, não use
NSDate
,CFAbsoluteTimeGetCurrent
ougettimeofday
para medir o tempo decorrido. Tudo isso depende do relógio do sistema, que pode mudar a qualquer momento devido a muitos motivos diferentes, como sincronização de horário da rede (NTP), atualização do relógio (geralmente ocorre para ajustar para desvio), ajustes de DST, segundos intercalados e assim por diante.Isso significa que, se você estiver medindo a velocidade de download ou upload, terá picos ou quedas repentinas em seus números que não se correlacionam com o que realmente aconteceu; seus testes de desempenho terão outliers incorretos estranhos; e seus temporizadores manuais serão acionados após durações incorretas. O tempo pode até retroceder e você acabar com deltas negativos, e você pode acabar com recursão infinita ou código morto (sim, eu fiz os dois).
Use
mach_absolute_time
. Ele mede os segundos reais desde que o kernel foi inicializado. É monotonicamente crescente (nunca retrocede) e não é afetado pelas configurações de data e hora. Como é difícil trabalhar com ele, aqui está um invólucro simples que forneceNSTimeInterval
:fonte
CACurrentMediaTime()
ao QuartzCore?@import Darwin;
vez de#include <mach/mach_time.h>
CFAbsoluteTimeGetCurrent()
retorna o tempo absoluto como umdouble
valor, mas não sei qual é sua precisão - ele pode atualizar apenas a cada dúzia de milissegundos ou pode atualizar a cada microssegundo, não sei.fonte
72.89674947369
segundos seria bastante incomum, considerando todos os outros valores que poderia ser. ;)Eu NÃO usaria
mach_absolute_time()
porque ele consulta uma combinação do kernel e do processador por um tempo absoluto usando ticks (provavelmente um tempo de atividade).O que eu usaria:
Esta função é otimizada para corrigir a diferença no software e hardware iOS e OSX.
Algo mais geek
O quociente de uma diferença em
mach_absolute_time()
eAFAbsoluteTimeGetCurrent()
está sempre em torno de 24000011.154871Aqui está um registro do meu aplicativo:
Por favor, note que o tempo resultado final é uma diferença em
CFAbsoluteTimeGetCurrent()
'sfonte
mach_absolute_time()
com ummach_timebase_info_data
e depois usei(long double)((mach_absolute_time()*time_base.numer)/((1000*1000)*time_base.denom));
. Para obter a base de tempo mach, você pode fazer(void)mach_timebase_info(&your_timebase);
Uso:
Resultado:
fonte
NSDate
depende do relógio do sistema que pode ser alterado a qualquer momento, resultando potencialmente em intervalos de tempo errados ou mesmo negativos. Emmach_absolute_time
vez disso, use para obter o tempo decorrido correto.mach_absolute_time
pode ser afetado por reinicializações do dispositivo. Em vez disso, use o horário do servidor.Além disso, aqui está como calcular um 64 bits
NSNumber
inicializado com a época Unix em milissegundos, caso seja assim que você deseja armazená-lo no CoreData. Eu precisava disso para meu aplicativo que interage com um sistema que armazena datas dessa forma.fonte
As funções baseadas em
mach_absolute_time
são boas para medições curtas.Mas, para medições longas, a advertência importante é que elas param de fazer tique-taque enquanto o dispositivo está dormindo.
Existe uma função para obter o tempo desde o boot. Não para durante o sono. Além disso,
gettimeofday
não é monotônico, mas em meus experimentos sempre vi que o tempo de inicialização muda quando o tempo do sistema muda, então acho que deve funcionar bem.E desde iOS 10 e macOS 10.12, podemos usar CLOCK_MONOTONIC:
Resumindo:
Date.timeIntervalSinceReferenceDate
- muda quando a hora do sistema muda, não monotônicaCFAbsoluteTimeGetCurrent()
- não monotônico, pode retrocederCACurrentMediaTime()
- para de funcionar quando o dispositivo está em repousotimeSinceBoot()
- não dorme, mas pode não ser monotônicoCLOCK_MONOTONIC
- não dorme, monotônico, compatível desde iOS 10fonte
Eu sei que este é antigo, mas até eu me vi vagando por ele novamente, então pensei em apresentar minha própria opção aqui.
A melhor aposta é verificar minha postagem no blog sobre isto: Cronometrando coisas em Objective-C: um cronômetro
Basicamente, escrevi uma classe que para de assistir de uma maneira muito básica, mas é encapsulada de forma que você só precisa fazer o seguinte:
E você acaba com:
no log ...
Novamente, confira minha postagem para um pouco mais ou faça o download aqui: MMStopwatch.zip
fonte
NSDate
depende do relógio do sistema que pode ser alterado a qualquer momento, resultando potencialmente em intervalos de tempo errados ou mesmo negativos. Emmach_absolute_time
vez disso, use para obter o tempo decorrido correto.Você pode obter a hora atual em milissegundos desde 1º de janeiro de 1970 usando um NSDate:
fonte
Para aqueles, precisamos da versão Swift da resposta de @Jeff Thompson:
Espero que isso lhe ajude.
fonte
NSDate
depende do relógio do sistema que pode ser alterado a qualquer momento, resultando potencialmente em intervalos de tempo errados ou mesmo negativos. Emmach_absolute_time
vez disso, use para obter o tempo decorrido correto.