NSTimer perfomance of device - objective-c

I want to run a timer that watches my game for some events that occur during the gameplay.
I would include the timer in the did load function. So the Timer is checking permanently if event1 happened or not.
[NSTimer scheduledTimerWithTimeInterval:0.001
target:self
selector:#selector(check_status_event1:)
userInfo:nil
repeats:YES];
I also try to set a pointer to the Timer to invalidate when needed.
- (IBAction)check_status_event1:(id)sender
{
//_stepper_event1_status_check.value (0 = no / 1 = yes)
if (_stepper_event1_status_check.value == 1) {
_stepper_event1_status_check.value = 0; //reset stepper again
[self event1_go:0];
}else{}
}
Question:
Is the interval of 0.001 o.k?
Is there a big influence to the device performance? Because there is permanently running an if statement (or more). Does it maybe also make the iPhone or iPad slower, when the game is sent to background via home button?
Can I use more of this timer at the same time? for example when I run 10 or 20 of them.
Is this the normal way to catch an event that occur during the game? For example a colidation of 2 objects. I also set some code with a timer after 1 sec (step1). after 2 sec (step2). after 3 sec (step3).... when I use such a timer, I can start the next step exactly at this time, when the step before has done. Maybe one step needs more then 1 sec. And I don't want to use animateWithDuration and Delay. And maybe an iPad 2 is slower in processing and reading the whole code as an iPad 4. And I don't want to start with step 2 when step 1 has not finished.
But what is about the performance of the iOS device. Is this a problem?
thank you
Philipp

Is the interval of 0.001 o.k?
Probably not. "The effective resolution of the time interval for a timer is limited to on the order of 50-100 milliseconds". You may set it to 0.001 but you are unlikely to get your timer on time.
Does it maybe also make the iPhone or iPad slower, when the game is sent to background
No it won't slow down the device when in background. iOS stops timers when app is in background.
Can I use more of this timer at the same time? for example when I run 10 or 20 of them.
Yes you can, but you may find a better solution.
I don't want to use animateWithDuration and Delay.
That will make your life easier. iOS goes into extends to make your animation smooth even if the device is under load.
Is this the normal way to catch an event that occur during the game?
No, unless your game doesn't update much, e.g. a turn-base game with no animation. Delivery time of timer event is not guaranteed. It may slip significantly. You would want to update you game state smoothly on every iteration, which is normally a frame. Do you have a frame update loop in your game? That would be the place to check for collisions and count time if needs be.
You are talking about noticing an event. A better design would be to use "push" rather than "pull". When an event happens it notifies all parties interested, not vice versa.

Related

NSTimer slowing down and pausing when minimized [duplicate]

I'm working on a macOS app (let's call it the "display app") that displays a clock and other data, which is controlled by another app (the "control app") on the same machine via a TCP connection. I have noticed that when the display app is idle for some time (> 60 sec.) and then schedules an NSTimer (with a .2 second interval), it takes a very long time before the timer fires for the first time (in the range of 6-10 seconds, sometimes longer.) That happens mostly when the display app is not frontmost (because the control app is.) Once the timer fired for the first time, it works as expected (with some small, expected delays in the timer) for some time.
But when the timer is running for a long time (more than 5 minutes), there are similar extreme delays between firing (also 6-10 seconds.) It looks like manually scheduling the timer with
[[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
postpones the problem a bit (using [NSTimer scheduledTimer...] makes that problem appear sooner than when manually adding it to the runloop.)
This causes a lot of trouble because the clock is not updating during that time.
I assume this happens because macOS considers the display app "idle" or "inactive" in some way.
Is there a way to prevent, control, or circumvent this behaviour?
This is App Nap. The display app can do the following to avoid napping:
id activity = [[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityUserInitiatedAllowingIdleSystemSleep reason:#"whatever"];
When it can allow napping again, you should do:
[[NSProcessInfo processInfo] endActivity:activity];

Prevent NSTimer firing delays in background app

I'm working on a macOS app (let's call it the "display app") that displays a clock and other data, which is controlled by another app (the "control app") on the same machine via a TCP connection. I have noticed that when the display app is idle for some time (> 60 sec.) and then schedules an NSTimer (with a .2 second interval), it takes a very long time before the timer fires for the first time (in the range of 6-10 seconds, sometimes longer.) That happens mostly when the display app is not frontmost (because the control app is.) Once the timer fired for the first time, it works as expected (with some small, expected delays in the timer) for some time.
But when the timer is running for a long time (more than 5 minutes), there are similar extreme delays between firing (also 6-10 seconds.) It looks like manually scheduling the timer with
[[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
postpones the problem a bit (using [NSTimer scheduledTimer...] makes that problem appear sooner than when manually adding it to the runloop.)
This causes a lot of trouble because the clock is not updating during that time.
I assume this happens because macOS considers the display app "idle" or "inactive" in some way.
Is there a way to prevent, control, or circumvent this behaviour?
This is App Nap. The display app can do the following to avoid napping:
id activity = [[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityUserInitiatedAllowingIdleSystemSleep reason:#"whatever"];
When it can allow napping again, you should do:
[[NSProcessInfo processInfo] endActivity:activity];

Set Up a Timer That Runs for the Life of an IOS App

I'm trying to figure out a way to have a timer that begins at the time that an app is installed and continues to run even when the app is in the background. I'm basically using the timer to periodically check the battery life of an external device that is linked to the phone. I've been told that the best way to do this is to use some sort of delegate calls to a timer function, but I'm fairly new to IOS and am pretty confused on how to do that. I know how to set up the timer and get the battery life, I'm however perplexed on how to keep the timer going through the life of the app. Any help you could give would be extreeemely appreciated! Thanks a bunch!
Running an app in the background (forever) isn't possible.
But while your app is running... you can set the repeats parameter of the method scheduledTimerWithInterval:target:selector:userInfo:repeats: to YES.
Here's a link to running it in the background for a certain period of time to perform a relatively large task.
run even when the app is in the background
Not possible. You can request an extra 10 minutes, but thats it. You will not be able to write your app as is.
For the timer part of your question, you can do this:
[NSTimer scheduledTimerWithTimeInterval:60.0
target:self
selector:#selector(checkBattery:)
userInfo:nil
repeats:YES];
But you should really be subscribing to the notifications on battery change events. Here is sample code from apple that shows how to do it.
coneybeare is right. This is iOS policy, which is in place exactly to prevent what you are trying to do, i.e. exhaust the iPhone's (or iPad's) battery life.

Show app running time in iPhone

I would like to write a counter that shows how many seconds an app has be running for. (textView) and the counter should be cumulative and starts from where it left off. Im new to iphone sdk.
you are going to have to do these things:
get the time when the app starts in applicationDidFinishLaunching: in your application delegate
check if you have an old time using NSUserDefaults
have a thread that updates the ui (your textView display, may i suggest using a label instead) with the ever increasing time using NSThread or NSTimer - i recommend NSThread. you will also need to perform your updates on your ui thread as updating your ui from a background thread can just get lost in the post.
store the end time in applicationWillTerminate: in your application delegate using NSUserDefaults
lots of googling ahead of you, have fun!

How to display time in seconds in Cocoa efficiently?

I want to display the time (including seconds) in an application in a text field, pretty simple. What I currently do is create a NSTimer that runs every 0.1 seconds that gets the system time and updates the text field. This seems like a terribly inefficient way to accomplish this. Is there a better way?
Are you displaying it to tenth-of-a-second (or finer) resolution?
If so, I see no problem. Usually, polling sucks because what you're checking might not have changed, but it's not like time is going to stop on you. So a tenth-of-a-second timer is fine.
If not, create a timer whose interval is the desired resolution, then get its fire date, round it down to the desired resolution (e.g., a whole second if you update every second), and set that as the new fire date. Then, your timer will only fire coincidentally with the times it's appropriate to update your clock view.
Note that while time always moves, it doesn't always move linearly: it may jump ahead or backward by an hour or half an hour, or any amount if the user (or ntpd) changes the system clock setting. On Mac OS X 10.6 and later, you can observe for the NSSystemClockDidChangeNotification, and re-adjust your timer's fire date when that happens.
How about you use NSTimer that runs every second and then you check the firing time and make sure it is exactly on the start of a second. You can use initWithFireDate:interval:target:selector:userInfo:repeats: or set the next invocation time appropriately using setFireDate: after the timer was created:
NSTimeInterval interval = [[timer fireDate] timeIntervalSinceReferenceDate];
NSTimeInterval nextFire = ceil(interval);
[timer setFireDate: [NSDate dateWithTimeIntervalSinceReferenceDate: nextFire];
Then you'll be sure that the timer fires as close to the needed time as possible and don't worry about the timer lagging behind because it resets itself after each firing using intended firing date and interval you provided, so it will always try to fire at exact second (but will fire whenever the run loop will be able to do that).
I'm not sure what else would be more efficient. As long as the callback for your timer is not doing anything too intensive, you're probably close to optimal.
How about using gettimeofday(2)? It returns much exact time information to use.