I'm trying to schedule an iOS notification at the same hour and minute every day.
First I define a DateComponents:
var components = DateComponents()
components.hour = 1
components.minute = 10
components.second = 0
Then use this to make the trigger:
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
Printing the components yields the expected result:
hour: 1 minute: 10 second: 0 isLeapMonth: false
But printing the trigger's next trigger date always shows a time 5 hours later than what it should:
Optional(2017-07-18 06:10:00 +0000)
Any idea what's going on here? I've tried setting the time zone on the components and it doesn't have any effect.
Edit: It looks like the notifications are actually firing at the correct time (I had a different issue which had broken them). I still can't explain the behavior of nextFireDate though.
in my app I have a UIProgressView that needs increase by +0.1 every 5 minutes. The method for doing this, but I know I have a problem, because I would like the calculations progressview five minutes even if my application is then closed should rely on real-time (iphone clock) and not that when my application is open ... I'll explain
I open my app and begin counting the minutes
Then I close my app
I open my app after 10 minutes
my view progress should have a value of +0.2 (0.1 every 5 minutes)
I know that to do that I should use NSDate but can not implement it in the right way, could someone help me with an example to better understand how to implement this?
Thank you all
in a few words what I look for is that the increase uiprogressview must be obtained from the clock iphone minutes ... this has to happen is if the app is open or closed .... just one more minute comes uiprogressview must change. .. in short, this should be a recover energy from a user
I think you should:
Store start date in some variable: NSDate *startDate = [NSDate new];
save actual start date to NSUserDefaults:
[[NSUserDefaults standardDefaults] setObject: startDate forKey: #"MyKey"];
Next, when your application will became active get the date from NSUserDefaults, calculate time interval between saved date and actual date:
NSTimeInterval secondsBetween = [[NSDate new] timeIntervalSinceDate: savedDate];
Now you can divide result by your progress interval (I guess in ViewWillAppear):
progress = secondsBetween/(5*60) * 0.1
If you want to refresh your progress after each time unit when your ViewController is active you should use NSTimer:
[NSTimer scheduledTimerWithTimeInterval: (5 * 60)
target:self
selector:#selector(refreshProgressMethod)
userInfo:nil
repeats:YES];
Upon app launch or whenever you want the progress to start, store current time:
let startTime = NSDate()
Then on refresh (can through timer setup to fire every few minutes, or in viewDidAppear()):
let timeDelta = Date().timeIntervalSince(startTime)
progressBar.progress = timeDelta/(60 * 5) * 0.1
Update:
Sounds like OP needs to know how to persist the progress start time between app termination and fresh launch. Like the other answer you could use the UserDefaults and check if a start time already exists. If it exists then use it otherwise create a new entry like so:
let userDefaultKey = "startTime"
var startTime = UserDefaults.standard.object(forKey: userDefaultKey)
if (startTime == nil)
{
startTime = Date()
UserDefaults.standard.set(startTime, forKey: userDefaultKey)
}
I want to get the CPU time used by a function in my app. It works properly on iOS Simulator. but when I run it on my iPhone it just gives 0.
var t = clock()
myLongRunningFunction()
t = clock() - t
I'm not familiar with the clock() function. Is that a UNIX function?
Terminal has a man page for a clock function but it says that it reports the processor time used in the current process.
I would suggest using the NSDate timeIntervalSinceReferenceDate function instead. That gives a value in seconds and decimal fractions of a second:
var startTime: NSTimeInterval
startTime = NSDate.timeIntervalSinceReferenceDate()
myLongRunningFunction() let secondsToRun =
NSDate.timeIntervalSinceReferenceDate() - startTime
print(format: "function took %.5f seconds to run", secondsToRun)
Where your result will be expressed in floating-point seconds.
Is there an easy way to get a time very precisely?
I need to calculate some delays between method calls. More specifically, I want to calculate the speed of scrolling in an UIScrollView.
NSDate and the timeIntervalSince* methods will return a NSTimeInterval which is a double with sub-millisecond accuracy. NSTimeInterval is in seconds, but it uses the double to give you greater precision.
In order to calculate millisecond time accuracy, you can do:
// 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;
Documentation on timeIntervalSinceNow.
There are many other ways to calculate this interval using NSDate, and I would recommend looking at the class documentation for NSDate which is found in NSDate Class Reference.
mach_absolute_time() can be used to get precise measurements.
See http://developer.apple.com/qa/qa2004/qa1398.html
Also available is CACurrentMediaTime(), which is essentially the same thing but with an easier-to-use interface.
(Note: This answer was written in 2009. See Pavel Alexeev's answer for the simpler POSIX clock_gettime() interfaces available in newer versions of macOS and iOS.)
Please do not use NSDate, CFAbsoluteTimeGetCurrent, or gettimeofday to measure elapsed time. These all depend on the system clock, which can change at any time due to many different reasons, such as network time sync (NTP) updating the clock (happens often to adjust for drift), DST adjustments, leap seconds, and so on.
This means that if you're measuring your download or upload speed, you will get sudden spikes or drops in your numbers that don't correlate with what actually happened; your performance tests will have weird incorrect outliers; and your manual timers will trigger after incorrect durations. Time might even go backwards, and you end up with negative deltas, and you can end up with infinite recursion or dead code (yeah, I've done both of these).
Use mach_absolute_time. It measures real seconds since the kernel was booted. It is monotonically increasing (will never go backwards), and is unaffected by date and time settings. Since it's a pain to work with, here's a simple wrapper that gives you NSTimeIntervals:
// 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() returns the absolute time as a double value, but I don't know what its precision is -- it might only update every dozen milliseconds, or it might update every microsecond, I don't know.
I would NOT use mach_absolute_time() because it queries a combination of the kernel and the processor for an absolute time using ticks (probably an uptime).
What I would use:
CFAbsoluteTimeGetCurrent();
This function is optimized to correct the difference in the iOS and OSX software and hardware.
Something Geekier
The quotient of a difference in mach_absolute_time() and AFAbsoluteTimeGetCurrent() is always around 24000011.154871
Here is a log of my app:
Please note that final result time is a difference in CFAbsoluteTimeGetCurrent()'s
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] -----------------------------------------------------
Functions based on mach_absolute_time are good for short measurements.
But for long measurements important caveat is that they stop ticking while device is asleep.
There is a function to get time since boot. It doesn't stop while sleeping. Also, gettimeofday is not monotonic, but in my experiments I've always see that boot time changes when system time changes, so I think it should work fine.
func timeSinceBoot() -> TimeInterval
{
var bootTime = timeval()
var currentTime = timeval()
var timeZone = timezone()
let mib = UnsafeMutablePointer<Int32>.allocate(capacity: 2)
mib[0] = CTL_KERN
mib[1] = KERN_BOOTTIME
var size = MemoryLayout.size(ofValue: bootTime)
var timeSinceBoot = 0.0
gettimeofday(¤tTime, &timeZone)
if sysctl(mib, 2, &bootTime, &size, nil, 0) != -1 && bootTime.tv_sec != 0 {
timeSinceBoot = Double(currentTime.tv_sec - bootTime.tv_sec)
timeSinceBoot += Double(currentTime.tv_usec - bootTime.tv_usec) / 1000000.0
}
return timeSinceBoot
}
And since iOS 10 and macOS 10.12 we can use CLOCK_MONOTONIC:
if #available(OSX 10.12, *) {
var uptime = timespec()
if clock_gettime(CLOCK_MONOTONIC_RAW, &uptime) == 0 {
return Double(uptime.tv_sec) + Double(uptime.tv_nsec) / 1000000000.0
}
}
To sum it up:
Date.timeIntervalSinceReferenceDate — changes when system time changes, not monotonic
CFAbsoluteTimeGetCurrent() — not monotonic, may go backward
CACurrentMediaTime() — stops ticking when device is asleep
timeSinceBoot() — doesn't sleep, but might be not monotonic
CLOCK_MONOTONIC — doesn't sleep, monotonic, supported since iOS 10
Also, here is how to calculate a 64-bit NSNumber initialized with the Unix epoch in milliseconds, in case that is how you want to store it in CoreData. I needed this for my app which interacts with a system that stores dates this way.
+ (NSNumber*) longUnixEpoch {
return [NSNumber numberWithLongLong:[[NSDate date] timeIntervalSince1970] * 1000];
}
#define CTTimeStart() NSDate * __date = [NSDate date]
#define CTTimeEnd(MSG) NSLog(MSG " %g",[__date timeIntervalSinceNow]*-1)
Usage:
CTTimeStart();
...
CTTimeEnd(#"that was a long time:");
Output:
2013-08-23 15:34:39.558 App-Dev[21229:907] that was a long time: .0023
I know this is an old one but even I found myself wandering past it again, so I thought I'd submit my own option here.
Best bet is to check out my blog post on this:
Timing things in Objective-C: A stopwatch
Basically, I wrote a class that does stop watching in a very basic way but is encapsulated so that you only need to do the following:
[MMStopwatchARC start:#"My Timer"];
// your work here ...
[MMStopwatchARC stop:#"My Timer"];
And you end up with:
MyApp[4090:15203] -> Stopwatch: [My Timer] runtime: [0.029]
in the log...
Again, check out my post for a little more or download it here:
MMStopwatch.zip
You can get current time in milliseconds since January 1st, 1970 using an NSDate:
- (double)currentTimeInMilliseconds {
NSDate *date = [NSDate date];
return [date timeIntervalSince1970]*1000;
}
For those we need the Swift version of the answer of #Jeff Thompson:
// Get a current time for where you want to start measuring from
var date = NSDate()
// do work...
// Find elapsed time and convert to milliseconds
// Use (-) modifier to conversion since receiver is earlier than now
var timePassed_ms: Double = date.timeIntervalSinceNow * -1000.0
I hope this help you.
trying to figure out how to get the time passed since timer started.
this is what i did :
Feel free to suggest other ways to get the time passed since the page loaded
Declared timer :
var runner = NSTimer()
runner = NSTimer.scheduledTimerWithTimeInterval(0.6, target: self, selector: Selector("time"), userInfo: nil, repeats: true)
Than tried this in the function,returns the interval i set(obviously)
func time() {
println(self.runner.timeInterval)
}
anyway if getting how much time passes since it started? (it's in the didload section so it like saying how much time passes since the page loaded). thanks ! :D
Put this in a playground. I added the loop just to create a time lag. Time in seconds down to fractions of a second.
var startTime = NSDate.timeIntervalSinceReferenceDate()
var currentTime: NSTimeInterval = 0
for var i = 0; i < 10000; i++ {
if i == 99 {
currentTime = NSDate.timeIntervalSinceReferenceDate()
println(i)
}
}
var elapsedTime = currentTime - startTime
println(Double(elapsedTime))
From:
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/#//apple_ref/occ/instp/NSDate/timeIntervalSinceReferenceDate
timeIntervalSinceReferenceDate
Returns the interval between the date object and January 1, 2001, at 12:00 a.m. GMT. (in seconds)
The method is establishing a startTime whenever you want to start. It is a time in seconds since the reference. Later we set the currentTime to be equal to the new time since the reference time. Subtracting one from the other gives elapsed time. There is several decimal place precision.