SKScene's update method gets a "currentTime" that is different from CFAbsoluteTimeGetCurrent() - objective-c

The problem can be reproduced in an freshly created SpriteKit project.
After creating a new project, I add two lines to the update: method of the MyScene class:
-(void)update:(CFTimeInterval)currentTime {
NSLog(#" currentTime = %f", currentTime);
NSLog(#"CFAbsoluteTimeGetCurrent() = %f", CFAbsoluteTimeGetCurrent());
}
Running this shows that currentTime is several orders of magnitude smaller than the time returned by CFAbsoluteTimeGetCurrent(). I searched for possible reasons, but found none. The only possibility I could think of is that currentTime is the time frame since some other date than 00:00:00 01.01.2000, but I have no idea what other reference point it would be using, and found nothing when searching online either.
What can I do to get the current time, calculated by the same rules that are used to calculate currentTime?

Nothing, unless you're willing to disassemble and understand the Sprite Kit framework code.
Though the problem is most likely explained by Sprite Kit taking CFAbsoluteTimeGetCurrent at an earlier point in time, which is then passed into the update: method. Simply the overhead of sending that message to the scene means that the two times can't be the same. Or the currentTime may not be obtained by CFAbsoluteTimeGetCurrent but some other means.
What you can do is to get the currentTime of the very first time update: runs and store it in an ivar. You can then use this time as the reference time for the scene.

currentTime is a CFTimeInterval, so I expect it is the interval between some point in time and the current time - probably the interval since a scene was started. If you let your scene running for a minute, do the values get close to 60.0 (60 seconds)?
CFAbsoluteTimeGetCurrent is a CFAbsoluteTime, that is the number of seconds since Jan 1st 2001, so that should always be around 500 million or so.

Related

Best way to do a massive data sync from HealthKit?

I am looking for a smart way to import ALL data for ALL time from HealthKit in a smart way for high volume users who log certain HealthKit values hundreds of times a day for months or years. I'm also looking to do this off the main thread and in a way that is robust to the fact that users can close the app whenever they feel like. Here's what my current implementation is:
- (void) fullHealthKitSyncFromEarliestDate {
dispatch_queue_t serialQueue = dispatch_queue_create("com.blah.queue", DISPATCH_QUEUE_SERIAL);
NSLog(#"fullHealthKitSyncFromEarliestDate");
NSDate *latestDate = [PFUser currentUser][#"earliestHKDate"];
if (!latestDate) latestDate = [NSDate date];
NSDate *earliestDate = [healthStore earliestPermittedSampleDate];
NSLog(#"earliest date %# and latest date %#", earliestDate, latestDate);
if ([earliestDate earlierDate:[[NSDate date] dateByAddingYears:-2]] == earliestDate) {
earliestDate = [[NSDate date] dateByAddingYears:-1];
}
__block NSDate *laterDate = latestDate;
__block NSDate *earlierDate = [latestDate dateByAddingMonths:-1];
int i = 0;
while ([earlierDate earlierDate:earliestDate] == earliestDate) {
// DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(i * 30 * NSEC_PER_SEC)), serialQueue, ^{
NSLog(#"calling sync from %# to %#", earlierDate, laterDate);
[self syncfromDate: earlierDate toDate:laterDate];
laterDate = [laterDate dateByAddingMonths:-1];
earlierDate = [laterDate dateByAddingMonths:-1];
earlierDate = [[earliestDate dateByAddingSeconds:1] laterDate:earlierDate];
});
}
}
I am having a few problems with the above code:
earlierDate is sometimes not getting updated for the next iteration. It's like there's some weird overlap that sometimes the same date range gets called twice or even more times.
Kernel memory allocation issues (as I retrieve objects I queue them for upload to a remote server)
Interface stops responding entirely even though this is all happening off the main queue. There may be something way down stream that gets called at the end of the entire query...but I'm still surprised the interface basically stops responding altogether. It usually does fine with similar syncing for short time periods. And here I'm just doing a month at a time in queries spaced 30 seconds apart
I realize without the details of additional code this may be too murky to address, but can people tell me what sort of solutions you have implemented for cases where you want to retrieve massive amounts of data from HealthKit. I realize I may get responses like 'that's what HealthKit is for...why are you duplicating all that data?'. Suffice it to say it's required and there's no way around it.
Also, am I just misunderstanding entirely how to use a serial queue?
Ideally I'd like to do the following: (1) Run only one query at a time in this for loop (2) and run them with some reasonable period of time between them, say 30 seconds apart, because at the end of each query I do need to do some interface updates on the main qeue (3) do all the queries on a background loop in such a way that it's not degrading interface performance and can be killed at any time the user decides he's gonna kill the app. That's what I thought I would achieve with the above...if folks can tell me where my threading is going wrong I'd really appreciate it. Thanks!

Precise measurement of time interval in CocoaTouch

I have a class which must have a property of some kind of timestamp, representing the moment of time when the instance of this class was created. And then when having multiple objects of this class I need to find the time interval between the creation of these objects.
And the usual interval is going to be up to 10 seconds, so I need precision of at least 1 second, but something like 0.1-0.001 second would be much better.
What is the best option to use for this property?
As far as I know, NSDate has precision up to 1 second.
I believe that I need something related to CFTimeInterval. I've used it for view animation with CADisplayLink. It provided the CFTimeInterval value for each moment of screen update and I could calculate the time interval between two CFTimeInterval's very easily.
But how do I assign the value to this CFTimeInterval at any moment of time?
NSDate will work, as Matthias Bauch's comment indicates. You can also just use CFTimeIntervals though:
CFTimeInterval currentTime = CFAbsoluteTimeGetCurrent();
Do note that this function and NSDate are both based on an absolute reference date (Jan 1, 2000 in this case). This means that if the system's clock is changed while your app is running, values obtained before the clock change won't correctly compare to values obtained afterward.

Objective-C iOS, set a delay for an update of text

I'm trying to find a solution to a problem I just stumbled upon.
Tried to search for it but it's not that I'm looking for.
I'm doing a GPS-app with two tabbars. I track the distance in the map-view (using CLLocation) and when I change tab to a different view the stringtext that say what distance it is from when I started don't update immediately, it take a couple of seconds.
And when I press the stop button I want it to either wait those couple of seconds so the real distance updates. But I dont want to freeze the app.
(*NSDate future = [NSDate dateWithTimeIntervalSinceNow: 3.0 ];
[NSThread sleepUntilDate:future];)
I'm saving the string with the distance in a cell in the second tab, so if I multitask while the app is going I want to just start the app and press stop. And then the new distance will be correct and saved. Hope I didn't confuse you with this much text I hope you understand what I asking for!
thx
[label performSelector:#selector(setText:) withObject:newText afterDelay:3.0];
So what you want to do is use dispatch_after:
dispatch_after(3 seconds, dispatch_get_main_queue(), ^
{
myLabel.text = <the value you want to appear>;
} );

Smoothness of NSProgressIndicator: incrementBy vs setDoubleValue

I suspect that NSProgressIndicator runs smoother when its value is updated through incrementBy as compared to setDoubleValue.
Does anyone know if there's any real difference between the two methods of updating its value?
I don't have any knowledge of the internals, but I would be very surprised if incrementBy were not the equivalent of
[self setDoubleValue:[self doubleValue] + delta];
Of course, since it has access to internal state, it could presumably skip all the method calls.But the act of actually rendering pixels to the screen almost certainly overpowers any minor performance difference between the two methods.
I suspect that NSProgressIndicator runs smoother when its value is
updated through incrementBy as compared to setDoubleValue.
Makes no difference on macOS 10.14. When I set the maxValue to 1000 and then have a timer call a method every 100 ms, it looks identical, whether the method always calls [self.progress incrementBy:1] or [self.progress setDoubleValue:self.step++], with step being an instance variable of type NSUInteger that is initially zero.

Pauses/computation between function execution?

I'm working on a game and the speed of the game is 60fps, giving me about 16ms to execute what I need to execute. What I'm finding tho is that certain code paths are taking a while to execute. At first I thought this must be an issue with memory allocation/deallocation. It could possibly be, but I have implemented object pooling for the more heavyweight objects, and this seems to have had little effect.
I have stripped out the offendingly large objects, and replaced them with a much simpler object, yet it still takes about 3ms to make this object. The simple object consists of two custom objects, 2 arrays, and 2 dictionaries. The large object is of an arbitrary complexity. Making the more complex larger objects seem to take linearly more time, taking up to 20-30ms. In many instances in my game I can make a much more complicated object in a fraction of the time. But somehow these specific locations in code cause a serious slowdown.
I am using the following code to profile my functions (from SO originally):
NSDate* methodStart = [NSDate date];
// My code here.
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(#"[CH] executionTime to create %# = %f", myObject , executionTime );
As best as I can confirm if I do something like the above in an inner and outer function, it looks like there can be a serious slowdown:
Inner function call completed: 4ms
...no code between inner and outer code except timer...
Outer function call completed: 8ms
My current theory is there is 'in-between' computation that occurs between the functions that is causing the serious slowdowns. As I'm new to Obj-C/C I'm not entirely sure what this slowdown could be. It could be threading, it could be because of memory alloc/autorelease/dealloc, or some other kind of unrelated issue. I have attempted to get more info from Instruments with little benefit.
So my question is: Does this sound logical? Is it possible that some kind of computation could be happening between my functions that would take up 2-4ms of cpu on an ipad2? And if my theory isn't possible, any ideas what it could be?
The best way to track down this type of problem is to use Instruments to profile the execution of the code. Often, you can run this against the code on the Mac under the simulator to see where the time is going, however, in this case you may need to profile it on your iPad to be certain.
Remove your NSDate-based profiling code, as NSDate can be a pretty heavy-weight object, especially when you put the results into the autorelease pool, which you are doing here.
If you feel you must do NSDate-based profiling, you should only need to create a single NSDate object and the use:
[methodStart timeIntervalSinceNow]
to calculate the time delta without having to create a separate object and perform a date subtraction operation.