उद्देश्य-सी में बीता हुआ समय


153

मुझे दो घटनाओं के बीच समय व्यतीत करने की आवश्यकता है, उदाहरण के लिए, एक यूआईवीवाई की उपस्थिति और उपयोगकर्ता की पहली प्रतिक्रिया।

मैं इसे ऑब्जेक्टिव-सी में कैसे प्राप्त कर सकता हूं?

जवाबों:


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

timeInterval उप-मिलीसेकंड परिशुद्धता के साथ, सेकंड में शुरू और अब के बीच का अंतर है।


18
@ निकोलसोज़ोज़ोल आप fabs(...)फ्लोट का पूर्ण मूल्य प्राप्त करने के लिए उपयोग कर सकते हैं । उदाहरण के लिए। NSTimeInterval timeInterval = fabs([start timeIntervalSinceNow]);
सो ओवर इट

1
लगता है कि समय का मूल्य नकारात्मक है।
जैकी

गुणा के साथ आप कर रहे हैं अच्छा -1 और - आप एक नकारात्मक मूल्य मिलता है
PinkFloydRocks

10
पर भरोसा [NSDate date]कीड़े ट्रैक करने के लिए, को देखने के लिए मुश्किल का कारण बन सकता इस उत्तर अधिक जानकारी के लिए।
सेंसफुल

@PinkFloydRocks - क्या? एक नकारात्मक मूल्य कभी वैध रूप से कैसे होगा?
टॉड लेहमन

228

आपको [NSDate date]समय के उद्देश्यों पर निर्भर नहीं होना चाहिए क्योंकि यह बीते हुए समय को खत्म या कम कर सकता है। ऐसे मामले भी हैं जहां आपका कंप्यूटर समय-यात्रा करेगा, क्योंकि बीता हुआ समय नकारात्मक होगा! (जैसे अगर घड़ी समय के दौरान पीछे की ओर चली गई।)

विंटर 2013 स्टैनफोर्ड आईओएस कोर्स (34:00) के "एडवांसड आईओएस जेस्चर रिक्रिएशन" व्याख्यान में आरिया हाघिगी के अनुसार , CACurrentMediaTime()यदि आपको एक सही समय अंतराल की आवश्यकता है , तो आपको इसका उपयोग करना चाहिए ।

उद्देश्य सी:

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

स्विफ्ट:

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

कारण यह है कि [NSDate date]सर्वर पर सिंक करता है, इसलिए यह "टाइम-सिंक हिचकी" को जन्म दे सकता है, जिससे बहुत मुश्किल से ट्रैक कीड़े हो सकते हैं। CACurrentMediaTime()दूसरी ओर, एक उपकरण समय है जो इन नेटवर्क सिंक के साथ नहीं बदलता है।

आपको अपने लक्ष्य की सेटिंग में क्वार्ट्जकोर फ्रेमवर्क को जोड़ना होगा ।


17
कृपया इसे बढ़ाएँ। हालाँकि मुझे लगता है कि हर कोई इस बात से सहमत हो सकता है कि NSDate आपका पहला विकल्प होना चाहिए, इस सुझाव से मेरा एक मुद्दा हल हो गया। [NSDate date]प्रेषण ब्लॉक के भीतर एक पूर्ण ब्लॉक के भीतर कॉल करते समय , मुझे वही "वर्तमान" समय मिल रहा था [NSDate date]जो निष्पादन से तुरंत पहले रिपोर्ट किया जा रहा था जिस बिंदु पर मेरे ब्लॉक बनाए गए थे। CACurrentMediaTime()इस मुद्दे को हल किया।
n00neimp0rtant

हम mm: ss जैसे प्रदर्शन के लिए elapsedTime का उपयोग कैसे करेंगे?
साइबरमेव


12
ध्यान रखें कि CACurrentMediaTime()जब डिवाइस नींद में प्रवेश करता है तो टिक टिकना बंद हो जाता है। यदि आप कंप्यूटर से डिस्कनेक्ट किए गए डिवाइस के साथ परीक्षण करते हैं, तो उसे लॉक करें, फिर ~ 10 मिनट प्रतीक्षा करें जो आप पाएंगे कि CACurrentMediaTime()घड़ी घड़ी के साथ नहीं रहता है।
रुसबिशप

जोड़ें और आयात करें #import <QuartzCore / QuartzCore.h>
स्टीवन ज़ोल्को

23

timeIntervalSinceDateविधि का प्रयोग करें

NSTimeInterval secondsElapsed = [secondDate timeIntervalSinceDate:firstDate];

NSTimeIntervalबस एक है double, NSDateइस तरह से परिभाषित करें:

typedef double NSTimeInterval;

15

यहां आने वाले किसी भी व्यक्ति को iOS के लिए getTickCount () के कार्यान्वयन की तलाश है, यहां विभिन्न स्रोतों को एक साथ रखने के बाद मेरा है।

पहले मेरे पास इस कोड में एक बग था (मैंने पहले 1000000 से विभाजित किया था) जो मेरे आईफोन 6 पर आउटपुट की कुछ मात्रा का कारण बन रहा था (शायद यह आईफोन 4 / आदि पर कोई समस्या नहीं थी या मैंने कभी इस पर ध्यान नहीं दिया)। ध्यान दें कि पहले उस डिवीजन को प्रदर्शन न करने से, टाइमबेस के अंश काफी बड़े होने पर ओवरफ्लो का कुछ जोखिम होता है। यदि कोई उत्सुक है, तो यहाँ बहुत अधिक जानकारी के साथ एक लिंक है: https://stackoverflow.com/a/23378064/588886

उस जानकारी के प्रकाश में, शायद यह Apple के फ़ंक्शन का उपयोग करने के लिए सुरक्षित है CACurrentMediaTime!

मैंने mach_timebase_infoकॉल को बेंचमार्क भी किया और मेरे iPhone 6 पर लगभग 19ns लगते हैं, इसलिए मैंने उस (न थ्रेडसेफ़) कोड को हटा दिया जो उस कॉल के आउटपुट को कैशिंग कर रहा था।

#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 के प्रत्येक मॉडल के लिए एक निरंतर हो सकता है। मेरे iPhone 6 पर यह था 125/3

समाधान का उपयोग CACurrentMediaTime()काफी तुच्छ है:

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

किसी को भी पता है कि mach_timebase_info कॉल पर एक निरर्थक (शून्य) कास्ट क्यों है?
साइमन टिलसन

@SimonTillson यह एक अच्छा सवाल है - या तो एक चेतावनी को चुप कराने के लिए आवश्यक था, या मैंने इसे कहीं और से कॉपी किया और इसे हटाने के लिए अभी नोटिस नहीं किया। मुझे याद नहीं आ रहा है।
वेन उरोदा

2
यह धागा सुरक्षित नहीं है। इसे वास्तविक मानों पर सेट करने से पहले mach_timebase_info()पास-इन mach_timebase_info_data_tको रीसेट कर देगा {0,0}, जो कई थ्रेड्स से कोड कहे जाने पर शून्य से विभाजन का कारण बन सकता है। dispatch_once()इसके बजाय का उपयोग करें (या CACurrentMediaTimeजो केवल सेकंड के लिए परिवर्तित समय है)।
Wonder.mice

धन्यवाद @ wonder.mice, मैंने अपना उत्तर अपडेट कर दिया है (मात्रा के संबंध में एक मुद्दा पाया गया है, मैं 6-वर्षीय मुझे दोषी ठहराता हूं ...)
वेन उरोदा


4

नीचे दिए गए NSDate वर्ग के timeIntervalSince1970 फ़ंक्शन का उपयोग करें:

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

मूल रूप से, यह वही है जो मैं 2 अलग-अलग तिथियों के बीच सेकंड में अंतर की तुलना करने के लिए उपयोग करता हूं। इस लिंक को भी यहाँ देखें


0

अन्य उत्तर सही हैं (एक चेतावनी * के साथ)। मैं उदाहरण का उपयोग दिखाने के लिए बस इस उत्तर को जोड़ता हूं:

- (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समय किसी भी क्षण आगे या पीछे कूद सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.